add communication ui/structure
This commit is contained in:
parent
a4e3b529bd
commit
314d53ab98
|
|
@ -11,7 +11,7 @@ set(CMAKE_AUTORCC ON)
|
||||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets Sql Xml REQUIRED Charts)
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets Sql Xml REQUIRED Charts)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS SvgWidgets)
|
find_package(Qt6 REQUIRED COMPONENTS SvgWidgets)
|
||||||
find_package(Qt6 COMPONENTS Network REQUIRED)
|
find_package(Qt6 COMPONENTS Network WebSockets REQUIRED)
|
||||||
find_package(PostgreSQL REQUIRED)
|
find_package(PostgreSQL REQUIRED)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -158,8 +158,9 @@ set_target_properties(DiagramDesigner PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils)
|
target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils diagramCommunication)
|
||||||
add_subdirectory(diagramCavas)
|
add_subdirectory(diagramCavas)
|
||||||
add_subdirectory(diagramUtils)
|
add_subdirectory(diagramUtils)
|
||||||
|
add_subdirectory(diagramCommunication)
|
||||||
|
|
||||||
file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin")
|
file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin")
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
|
||||||
include/projectIconSetting.h
|
include/projectIconSetting.h
|
||||||
include/projectIconSelectionDlg.h
|
include/projectIconSelectionDlg.h
|
||||||
include/projectDiagramNameInput.h
|
include/projectDiagramNameInput.h
|
||||||
|
include/diagramConnectSetting.h
|
||||||
include/diagramEditor/editPanel.h
|
include/diagramEditor/editPanel.h
|
||||||
include/diagramEditor/editView.h
|
include/diagramEditor/editView.h
|
||||||
include/diagramEditor/editScene.h
|
include/diagramEditor/editScene.h
|
||||||
|
|
@ -112,6 +113,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
|
||||||
include/util/scalingSelector.h
|
include/util/scalingSelector.h
|
||||||
include/util/selectorManager.h
|
include/util/selectorManager.h
|
||||||
include/util/subMovingSelector.h
|
include/util/subMovingSelector.h
|
||||||
|
include/instance/dataAccessor.h
|
||||||
../common/include/httpInterface.h
|
../common/include/httpInterface.h
|
||||||
../common/include/tools.h
|
../common/include/tools.h
|
||||||
../common/include/global.h
|
../common/include/global.h
|
||||||
|
|
@ -160,6 +162,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
|
||||||
source/projectIconSetting.cpp
|
source/projectIconSetting.cpp
|
||||||
source/projectIconSelectionDlg.cpp
|
source/projectIconSelectionDlg.cpp
|
||||||
source/projectDiagramNameInput.cpp
|
source/projectDiagramNameInput.cpp
|
||||||
|
source/diagramConnectSetting.cpp
|
||||||
source/diagramEditor/editPanel.cpp
|
source/diagramEditor/editPanel.cpp
|
||||||
source/diagramEditor/editView.cpp
|
source/diagramEditor/editView.cpp
|
||||||
source/diagramEditor/editScene.cpp
|
source/diagramEditor/editScene.cpp
|
||||||
|
|
@ -232,6 +235,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
|
||||||
source/util/scalingSelector.cpp
|
source/util/scalingSelector.cpp
|
||||||
source/util/selectorManager.cpp
|
source/util/selectorManager.cpp
|
||||||
source/util/subMovingSelector.cpp
|
source/util/subMovingSelector.cpp
|
||||||
|
source/instance/dataAccessor.cpp
|
||||||
../common/source/httpInterface.cpp
|
../common/source/httpInterface.cpp
|
||||||
../common/source/baseProperty.cpp
|
../common/source/baseProperty.cpp
|
||||||
../common/source/tools.cpp
|
../common/source/tools.cpp
|
||||||
|
|
@ -263,6 +267,7 @@ set(UI_FILES
|
||||||
ui/monitorDetailAttributeDlg.ui
|
ui/monitorDetailAttributeDlg.ui
|
||||||
ui/monitorDisplaySettingDlg.ui
|
ui/monitorDisplaySettingDlg.ui
|
||||||
ui/loadMonitorPageDlg.ui
|
ui/loadMonitorPageDlg.ui
|
||||||
|
ui/diagramConnectSetting.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
|
@ -288,6 +293,7 @@ target_link_libraries(diagramCavas PUBLIC Qt${QT_VERSION_MAJOR}::Core
|
||||||
target_link_libraries(diagramCavas PRIVATE Qt6::SvgWidgets)
|
target_link_libraries(diagramCavas PRIVATE Qt6::SvgWidgets)
|
||||||
target_link_libraries(diagramCavas PRIVATE Qt6::Xml)
|
target_link_libraries(diagramCavas PRIVATE Qt6::Xml)
|
||||||
target_link_libraries(diagramCavas PRIVATE Qt6::Network)
|
target_link_libraries(diagramCavas PRIVATE Qt6::Network)
|
||||||
|
target_link_libraries(diagramCavas PRIVATE Qt6::WebSockets)
|
||||||
target_link_libraries(diagramCavas PRIVATE Qt6::Charts)
|
target_link_libraries(diagramCavas PRIVATE Qt6::Charts)
|
||||||
target_link_libraries(diagramCavas PRIVATE Qt6::Sql ${PostgreSQL_LIBRARIES})
|
target_link_libraries(diagramCavas PRIVATE Qt6::Sql ${PostgreSQL_LIBRARIES})
|
||||||
|
|
||||||
|
|
@ -298,6 +304,7 @@ option(BUILD_SHARED_LIBS "Build as shared library" ON)
|
||||||
target_include_directories(diagramCavas PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(diagramCavas PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
target_link_libraries(diagramCavas PRIVATE diagramUtils)
|
target_link_libraries(diagramCavas PRIVATE diagramUtils)
|
||||||
|
target_link_libraries(diagramCavas PRIVATE diagramCommunication)
|
||||||
|
|
||||||
target_compile_definitions(diagramCavas
|
target_compile_definitions(diagramCavas
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class EditBaseItem;
|
||||||
class MonitorPanel;
|
class MonitorPanel;
|
||||||
class CornerMonitorLauncher;
|
class CornerMonitorLauncher;
|
||||||
class LoadMonitorPageDlg;
|
class LoadMonitorPageDlg;
|
||||||
|
class DiagramConnectSetting;
|
||||||
|
|
||||||
class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea
|
class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea
|
||||||
{
|
{
|
||||||
|
|
@ -64,6 +65,8 @@ public slots:
|
||||||
void onSignal_deleteDiagram(DiagramInfo);
|
void onSignal_deleteDiagram(DiagramInfo);
|
||||||
void onSignal_selectDiagram(DiagramInfo);
|
void onSignal_selectDiagram(DiagramInfo);
|
||||||
|
|
||||||
|
void onSignal_openNetSetting(); //打开网络设置
|
||||||
|
|
||||||
void onCreateTestBaseModelDiagram(); //生成测试基模图
|
void onCreateTestBaseModelDiagram(); //生成测试基模图
|
||||||
/******************************生成组态***********************************/
|
/******************************生成组态***********************************/
|
||||||
void onSignal_createEditPanel(QString,QUuid);
|
void onSignal_createEditPanel(QString,QUuid);
|
||||||
|
|
@ -104,6 +107,7 @@ private:
|
||||||
QString _curPage;
|
QString _curPage;
|
||||||
CornerMonitorLauncher* _cornerButton; //简略菜单呼出按钮
|
CornerMonitorLauncher* _cornerButton; //简略菜单呼出按钮
|
||||||
LoadMonitorPageDlg* _loadMonitorPageDlg;
|
LoadMonitorPageDlg* _loadMonitorPageDlg;
|
||||||
|
DiagramConnectSetting* _connectSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef DIAGRAMCONNECTSETTING_H
|
||||||
|
#define DIAGRAMCONNECTSETTING_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "global.h"
|
||||||
|
/*******************************************************
|
||||||
|
网络连接设置
|
||||||
|
********************************************************/
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui { class diagramConnectSetting; }
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
struct ChannelConfig;
|
||||||
|
|
||||||
|
class DiagramConnectSetting : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DiagramConnectSetting(QWidget *parent = nullptr);
|
||||||
|
~DiagramConnectSetting();
|
||||||
|
|
||||||
|
void showDlg();
|
||||||
|
public slots:
|
||||||
|
void onTestHttpClicked();
|
||||||
|
void onTestWebsocketClicked();
|
||||||
|
void onOkClicked();
|
||||||
|
void onCancelClicked();
|
||||||
|
private:
|
||||||
|
void initial();
|
||||||
|
void updateByConfig(ChannelConfig,int nType = 0); //0http 1websocket
|
||||||
|
private:
|
||||||
|
Ui::diagramConnectSetting *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef DATAACCESSOR_H
|
||||||
|
#define DATAACCESSOR_H
|
||||||
|
|
||||||
|
/*********中转、处理网络数据*********/
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class DataAccessor : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DataAccessor(QObject *parent = nullptr);
|
||||||
|
~DataAccessor();
|
||||||
|
private:
|
||||||
|
QMap<QString,QMap<quint64,double>> _realTimeData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -18,11 +18,15 @@
|
||||||
#include "basePropertyManager.h"
|
#include "basePropertyManager.h"
|
||||||
#include "cornerMonitorLauncher.h"
|
#include "cornerMonitorLauncher.h"
|
||||||
#include "loadMonitorPageDlg.h"
|
#include "loadMonitorPageDlg.h"
|
||||||
|
#include "diagramConnectSetting.h"
|
||||||
|
#include "diagramCommunication/include/communicationManager.h"
|
||||||
|
#include "diagramCommunication/include/configManager.h"
|
||||||
|
|
||||||
DiagramCavas::DiagramCavas(QWidget *parent)
|
DiagramCavas::DiagramCavas(QWidget *parent)
|
||||||
: QMdiArea(parent)
|
: QMdiArea(parent)
|
||||||
,_cornerButton(nullptr)
|
,_cornerButton(nullptr)
|
||||||
,_loadMonitorPageDlg(nullptr)
|
,_loadMonitorPageDlg(nullptr)
|
||||||
|
,_connectSetting(nullptr)
|
||||||
{
|
{
|
||||||
_pageIndex = 0;
|
_pageIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +81,19 @@ void DiagramCavas::initial()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(_loadMonitorPageDlg,&LoadMonitorPageDlg::monitorSelected,this,&DiagramCavas::onSignal_monitorSelected);
|
connect(_loadMonitorPageDlg,&LoadMonitorPageDlg::monitorSelected,this,&DiagramCavas::onSignal_monitorSelected);
|
||||||
|
_connectSetting = new DiagramConnectSetting(this);
|
||||||
|
|
||||||
|
// 初始化通信管理器
|
||||||
|
CommunicationManager* comm = CommunicationManager::instance();
|
||||||
|
comm->initialize();
|
||||||
|
|
||||||
|
// 加载配置
|
||||||
|
ConfigManager* config = ConfigManager::instance();
|
||||||
|
config->loadConfig("config.json");
|
||||||
|
|
||||||
|
// 应用配置
|
||||||
|
comm->updateHttpConfig(config->getHttpConfig());
|
||||||
|
comm->updateWebSocketConfig(config->getWebSocketConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent)
|
void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent)
|
||||||
|
|
@ -432,6 +449,13 @@ void DiagramCavas::onSignal_selectDiagram(DiagramInfo info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiagramCavas::onSignal_openNetSetting()
|
||||||
|
{
|
||||||
|
if(_connectSetting){
|
||||||
|
_connectSetting->showDlg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DiagramCavas::removePanel(PowerEntity* pEntity)
|
void DiagramCavas::removePanel(PowerEntity* pEntity)
|
||||||
{
|
{
|
||||||
QMap<QString,QPair<DrawingPanel*,QMdiSubWindow*>>::Iterator iter;
|
QMap<QString,QPair<DrawingPanel*,QMdiSubWindow*>>::Iterator iter;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "diagramConnectSetting.h"
|
||||||
|
#include "ui_diagramConnectSetting.h"
|
||||||
|
#include "diagramCommunication/include/configManager.h"
|
||||||
|
|
||||||
|
DiagramConnectSetting::DiagramConnectSetting(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::diagramConnectSetting)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
|
||||||
|
initial();
|
||||||
|
}
|
||||||
|
|
||||||
|
DiagramConnectSetting::~DiagramConnectSetting()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::initial()
|
||||||
|
{
|
||||||
|
connect(ui->btn_testHttp,&QPushButton::clicked,this,&DiagramConnectSetting::onTestHttpClicked);
|
||||||
|
connect(ui->btn_testWebsoc,&QPushButton::clicked,this,&DiagramConnectSetting::onTestWebsocketClicked);
|
||||||
|
connect(ui->btn_ok,&QPushButton::clicked,this,&DiagramConnectSetting::onOkClicked);
|
||||||
|
connect(ui->btn_cancel,&QPushButton::clicked,this,&DiagramConnectSetting::onCancelClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::updateByConfig(ChannelConfig info,int nType)
|
||||||
|
{
|
||||||
|
if(nType == 0){
|
||||||
|
ui->le_httpName->setText(info.name);
|
||||||
|
ui->le_httpIp->setText(info.endpoint);
|
||||||
|
ui->le_httpOver->setText(QString::number(info.timeout));
|
||||||
|
}
|
||||||
|
else if(nType == 1){
|
||||||
|
ui->le_websocName->setText(info.name);
|
||||||
|
ui->le_websocIp->setText(info.endpoint);
|
||||||
|
ui->le_websocOver->setText(QString::number(info.timeout));
|
||||||
|
ui->le_websocHeart->setText(QString::number(info.heartbeatInterval));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::showDlg()
|
||||||
|
{
|
||||||
|
show();
|
||||||
|
ConfigManager* config = ConfigManager::instance();
|
||||||
|
auto httpInfo = config->getHttpConfig();
|
||||||
|
updateByConfig(httpInfo,0);
|
||||||
|
auto socketInfo = config->getWebSocketConfig();
|
||||||
|
updateByConfig(socketInfo,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::onTestHttpClicked()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::onTestWebsocketClicked()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::onOkClicked()
|
||||||
|
{
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagramConnectSetting::onCancelClicked()
|
||||||
|
{
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "instance/dataAccessor.h"
|
||||||
|
|
||||||
|
DataAccessor::DataAccessor(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DataAccessor::~DataAccessor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -112,29 +112,6 @@ void MonitorDisplaySettingDlg::onCheckboxToggled(bool val)
|
||||||
|
|
||||||
void MonitorDisplaySettingDlg::onIconSelectClicked()
|
void MonitorDisplaySettingDlg::onIconSelectClicked()
|
||||||
{
|
{
|
||||||
// if(!_curMeta.isEmpty() && !_curModel.isEmpty()){
|
|
||||||
// auto mapAllSvg = ProjectModelManager::instance().getData()[_curMeta][_curModel].modelSetting.mapSvg;
|
|
||||||
// ProjectIconSelectionDlg dialog(mapAllSvg, this);
|
|
||||||
// if (dialog.exec() == QDialog::Accepted) {
|
|
||||||
// QByteArray selectedSVG = dialog.selectedSVG();
|
|
||||||
// if (!selectedSVG.isEmpty()) {
|
|
||||||
// QSvgRenderer renderer(selectedSVG);
|
|
||||||
// QPixmap pixmap(32, 32);
|
|
||||||
// pixmap.fill(Qt::transparent);
|
|
||||||
// QPainter painter(&pixmap);
|
|
||||||
// renderer.render(&painter);
|
|
||||||
|
|
||||||
// ui->btn_selectIcon->setIcon(QIcon(pixmap));
|
|
||||||
// if (validateSvgData(selectedSVG)) {
|
|
||||||
// updateIconDisplay(selectedSVG);
|
|
||||||
|
|
||||||
// if(_curType.isValid() && _curState.isValid()){
|
|
||||||
// _tempSetting[_curType][_curState].bytPicture = selectedSVG;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if(_curMeta.isEmpty() || _curModel.isEmpty()){
|
if(_curMeta.isEmpty() || _curModel.isEmpty()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -217,22 +194,6 @@ void MonitorDisplaySettingDlg::onDeviceComboBoxChanged(const QString& str)
|
||||||
|
|
||||||
void MonitorDisplaySettingDlg::onStateComboBoxChanged(const QString& str)
|
void MonitorDisplaySettingDlg::onStateComboBoxChanged(const QString& str)
|
||||||
{
|
{
|
||||||
/*if(_tempSetting.contains(_curType)){
|
|
||||||
monitorItemStateStruct keyState;
|
|
||||||
keyState.sState = str;
|
|
||||||
keyState.eState = monitorItemState(ui->cb_state->currentData().toInt());
|
|
||||||
if(_tempSetting[_curType].contains(keyState)){
|
|
||||||
saveSetting(_curType,_curState);
|
|
||||||
auto info = _tempSetting[_curType][keyState];
|
|
||||||
ui->checkBox_custom->setChecked(info.bEnable);
|
|
||||||
if(_curModel != info.sModel){
|
|
||||||
_curModel = info.sModel;
|
|
||||||
}
|
|
||||||
_curState = keyState;
|
|
||||||
loadSetting(_curType,_curState);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (str.isEmpty() || str == _curState.sState) {
|
if (str.isEmpty() || str == _curState.sState) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,469 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>diagramConnectSetting</class>
|
||||||
|
<widget class="QDialog" name="diagramConnectSetting">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>393</width>
|
||||||
|
<height>502</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>21</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(196, 196, 196);</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(0, 0, 0);
|
||||||
|
font: 12pt "Microsoft YaHei UI";</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>网络通信设置</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>302</width>
|
||||||
|
<height>18</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>HTTP设置</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>HTTP服务器配置</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="horizontalSpacing">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>ms</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>超时时间:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="le_httpIp"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>连接名称:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>217</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="le_httpName"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="le_httpOver">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>服务器地址</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>连接测试</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_testHttp">
|
||||||
|
<property name="text">
|
||||||
|
<string>测试连接</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>状态:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_httpState">
|
||||||
|
<property name="text">
|
||||||
|
<string>未连接</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>WebSoket设置</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="title">
|
||||||
|
<string>WebSocket服务器配置</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<item row="3" column="3" colspan="2">
|
||||||
|
<spacer name="horizontalSpacer_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>214</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>服务器地址</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>连接名称:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>ms</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="le_websocOver">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>超时时间:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>心跳间隔:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="4">
|
||||||
|
<widget class="QLineEdit" name="le_websocName"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="le_websocHeart">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="4">
|
||||||
|
<widget class="QLineEdit" name="le_websocIp"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="3">
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>ms</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3" colspan="2">
|
||||||
|
<spacer name="horizontalSpacer_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>217</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox_5">
|
||||||
|
<property name="title">
|
||||||
|
<string>连接测试</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_testWebsoc">
|
||||||
|
<property name="text">
|
||||||
|
<string>测试连接</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>状态:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_websocState">
|
||||||
|
<property name="text">
|
||||||
|
<string>未连接</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>操作日志</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="lst_log"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_ok">
|
||||||
|
<property name="text">
|
||||||
|
<string>保存</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_cancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>取消</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
project(diagramCommunication)
|
||||||
|
|
||||||
|
set(DIAGRACOMMUNICATION_HEADER_FILES
|
||||||
|
include/channelConfig.h
|
||||||
|
include/baseChannel.h
|
||||||
|
include/communicationManager.h
|
||||||
|
include/httpChannel.h
|
||||||
|
include/webSocketChannel.h
|
||||||
|
include/configManager.h
|
||||||
|
include/uiCommunicationBus.h
|
||||||
|
include/dataProcessor.h
|
||||||
|
../common/include/compiler.hpp
|
||||||
|
../common/include/export.hpp
|
||||||
|
../common/include/operatingSystem.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(DIAGRACOMMUNICATION_SOURCE_FILES
|
||||||
|
source/communicationManager.cpp
|
||||||
|
source/baseChannel.cpp
|
||||||
|
source/webSocketChannel.cpp
|
||||||
|
source/httpChannel.cpp
|
||||||
|
source/configManager.cpp
|
||||||
|
source/uiCommunicationBus.cpp
|
||||||
|
source/dataProcessor.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
qt_add_library(diagramCommunication SHARED
|
||||||
|
MANUAL_FINALIZATION
|
||||||
|
${DIAGRACOMMUNICATION_HEADER_FILES}
|
||||||
|
${DIAGRACOMMUNICATION_SOURCE_FILES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
add_library(diagramCommunication SHARED
|
||||||
|
${DIAGRACOMMUNICATION_HEADER_FILES}
|
||||||
|
${DIAGRACOMMUNICATION_SOURCE_FILES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(diagramCommunication PUBLIC Qt${QT_VERSION_MAJOR}::Core)
|
||||||
|
target_link_libraries(diagramCommunication PRIVATE Qt6::Xml)
|
||||||
|
target_link_libraries(diagramCommunication PRIVATE Qt6::Network)
|
||||||
|
target_link_libraries(diagramCommunication PRIVATE Qt6::WebSockets)
|
||||||
|
target_link_libraries(diagramCommunication PRIVATE Qt6::Sql ${PostgreSQL_LIBRARIES})
|
||||||
|
|
||||||
|
option(BUILD_SHARED_LIBS "Build as shared library" ON)
|
||||||
|
|
||||||
|
|
||||||
|
target_include_directories(diagramCommunication PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
target_compile_definitions(diagramCommunication
|
||||||
|
PUBLIC
|
||||||
|
DIAGRAM_DESIGNER_SHARED
|
||||||
|
PRIVATE
|
||||||
|
DIAGRAM_DESIGNER_EXPORTS
|
||||||
|
#QT_NO_KEYWORDS
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// ConfigManager.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "channelConfig.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include "export.hpp"
|
||||||
|
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC ConfigManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ConfigManager* instance();
|
||||||
|
|
||||||
|
// 加载配置
|
||||||
|
bool loadConfig(const QString& configFile = "");
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
bool saveConfig();
|
||||||
|
|
||||||
|
// 获取配置
|
||||||
|
ChannelConfig getHttpConfig() const;
|
||||||
|
ChannelConfig getWebSocketConfig() const;
|
||||||
|
|
||||||
|
// 更新配置
|
||||||
|
void setHttpConfig(const ChannelConfig& config);
|
||||||
|
void setWebSocketConfig(const ChannelConfig& config);
|
||||||
|
|
||||||
|
// 获取配置路径
|
||||||
|
QString configFilePath() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void configLoaded();
|
||||||
|
void configSaved();
|
||||||
|
void httpConfigChanged(const ChannelConfig& config);
|
||||||
|
void websocketConfigChanged(const ChannelConfig& config);
|
||||||
|
private:
|
||||||
|
ConfigManager(QObject* parent = nullptr);
|
||||||
|
bool createDefaultConfig();
|
||||||
|
ChannelConfig getDefaultHttpConfig() const;
|
||||||
|
ChannelConfig getDefaultWebSocketConfig() const;
|
||||||
|
|
||||||
|
ChannelConfig m_httpConfig;
|
||||||
|
ChannelConfig m_websocketConfig;
|
||||||
|
QString m_configFile;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMap>
|
||||||
|
#include "export.hpp"
|
||||||
|
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC BaseChannel : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct ChannelConfig {
|
||||||
|
QString channelId;
|
||||||
|
QUrl endpoint;
|
||||||
|
int timeout = 30000; // 超时时间(ms)
|
||||||
|
int reconnectInterval = 5000; // 重连间隔(ms)
|
||||||
|
int maxRetries = 3; // 最大重试次数
|
||||||
|
QVariantMap params; // 自定义参数
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit BaseChannel(const ChannelConfig& config, QObject* parent = nullptr);
|
||||||
|
virtual ~BaseChannel();
|
||||||
|
|
||||||
|
// 连接管理
|
||||||
|
virtual bool connect() = 0;
|
||||||
|
virtual bool disconnect() = 0;
|
||||||
|
virtual bool isConnected() const = 0;
|
||||||
|
|
||||||
|
// 数据发送
|
||||||
|
virtual bool send(const QByteArray& data) = 0;
|
||||||
|
|
||||||
|
// 信息获取
|
||||||
|
QString channelId() const { return m_config.channelId; }
|
||||||
|
ChannelConfig config() const { return m_config; }
|
||||||
|
QUrl endpoint() const { return m_config.endpoint; }
|
||||||
|
|
||||||
|
// 控制
|
||||||
|
void setAutoReconnect(bool enable);
|
||||||
|
bool isAutoReconnect() const { return m_autoReconnect; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connected();
|
||||||
|
void disconnected();
|
||||||
|
void dataReceived(const QByteArray& data);
|
||||||
|
void errorOccurred(const QString& error);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// 公共方法
|
||||||
|
void startReconnectTimer();
|
||||||
|
void stopReconnectTimer();
|
||||||
|
void reconnect();
|
||||||
|
|
||||||
|
// 工具方法
|
||||||
|
QByteArray generateMessageId() const;
|
||||||
|
qint64 currentTimestamp() const;
|
||||||
|
|
||||||
|
// 成员变量
|
||||||
|
ChannelConfig m_config;
|
||||||
|
bool m_autoReconnect = true;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onReconnectTimeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer* m_reconnectTimer = nullptr;
|
||||||
|
int m_reconnectCount = 0;
|
||||||
|
QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
// ChannelConfig.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include "export.hpp"
|
||||||
|
|
||||||
|
// 简化配置结构
|
||||||
|
struct DIAGRAM_DESIGNER_PUBLIC ChannelConfig {
|
||||||
|
// 通用配置
|
||||||
|
QString id; // 通道ID: "http_channel" 或 "websocket_channel"
|
||||||
|
QString name; // 通道名称
|
||||||
|
QString endpoint; // 连接地址
|
||||||
|
int timeout = 30000; // 超时时间(ms)
|
||||||
|
bool enabled = true; // 是否启用
|
||||||
|
bool autoConnect = false; // 是否自动连接
|
||||||
|
|
||||||
|
// 认证
|
||||||
|
QString username;
|
||||||
|
QString password;
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
bool connected = false;
|
||||||
|
QDateTime lastConnectTime;
|
||||||
|
int errorCount = 0;
|
||||||
|
|
||||||
|
// HTTP特有
|
||||||
|
QVariantMap headers; // HTTP头
|
||||||
|
|
||||||
|
// WebSocket特有
|
||||||
|
int heartbeatInterval = 30000; // 心跳间隔
|
||||||
|
|
||||||
|
// 转换为Map
|
||||||
|
QVariantMap toMap() const {
|
||||||
|
return {
|
||||||
|
{"id", id},
|
||||||
|
{"name", name},
|
||||||
|
{"endpoint", endpoint},
|
||||||
|
{"timeout", timeout},
|
||||||
|
{"enabled", enabled},
|
||||||
|
{"autoConnect", autoConnect},
|
||||||
|
{"username", username},
|
||||||
|
{"password", password},
|
||||||
|
{"connected", connected},
|
||||||
|
{"lastConnectTime", lastConnectTime.toString(Qt::ISODate)},
|
||||||
|
{"errorCount", errorCount},
|
||||||
|
{"headers", headers},
|
||||||
|
{"heartbeatInterval", heartbeatInterval}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从Map创建
|
||||||
|
static ChannelConfig fromMap(const QVariantMap& map) {
|
||||||
|
ChannelConfig config;
|
||||||
|
config.id = map.value("id").toString();
|
||||||
|
config.name = map.value("name").toString();
|
||||||
|
config.endpoint = map.value("endpoint").toString();
|
||||||
|
config.timeout = map.value("timeout", 30000).toInt();
|
||||||
|
config.enabled = map.value("enabled", true).toBool();
|
||||||
|
config.autoConnect = map.value("autoConnect", false).toBool();
|
||||||
|
config.username = map.value("username").toString();
|
||||||
|
config.password = map.value("password").toString();
|
||||||
|
config.connected = map.value("connected", false).toBool();
|
||||||
|
config.lastConnectTime = QDateTime::fromString(
|
||||||
|
map.value("lastConnectTime").toString(), Qt::ISODate);
|
||||||
|
config.errorCount = map.value("errorCount", 0).toInt();
|
||||||
|
config.headers = map.value("headers").toMap();
|
||||||
|
config.heartbeatInterval = map.value("heartbeatInterval", 30000).toInt();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
// CommunicationManager.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "channelConfig.h"
|
||||||
|
#include "httpChannel.h"
|
||||||
|
#include "webSocketChannel.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include "export.hpp"
|
||||||
|
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC CommunicationManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CommunicationManager* instance();
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
bool initialize();
|
||||||
|
|
||||||
|
// HTTP通道操作
|
||||||
|
bool connectHttp();
|
||||||
|
bool disconnectHttp();
|
||||||
|
bool sendHttpRequest(const QString& path,
|
||||||
|
const QByteArray& data = QByteArray(),
|
||||||
|
const QString& method = "GET");
|
||||||
|
|
||||||
|
// WebSocket通道操作
|
||||||
|
bool connectWebSocket();
|
||||||
|
bool disconnectWebSocket();
|
||||||
|
bool sendWebSocketMessage(const QByteArray& data);
|
||||||
|
bool sendWebSocketText(const QString& text);
|
||||||
|
|
||||||
|
// 状态查询
|
||||||
|
bool isHttpConnected() const;
|
||||||
|
bool isWebSocketConnected() const;
|
||||||
|
ChannelConfig getHttpConfig() const;
|
||||||
|
ChannelConfig getWebSocketConfig() const;
|
||||||
|
|
||||||
|
// 配置更新
|
||||||
|
void updateHttpConfig(const ChannelConfig& config);
|
||||||
|
void updateWebSocketConfig(const ChannelConfig& config);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// HTTP通道信号
|
||||||
|
void httpConnected();
|
||||||
|
void httpDisconnected();
|
||||||
|
void httpDataReceived(const QByteArray& data);
|
||||||
|
void httpError(const QString& error);
|
||||||
|
|
||||||
|
// WebSocket通道信号
|
||||||
|
void websocketConnected();
|
||||||
|
void websocketDisconnected();
|
||||||
|
void websocketDataReceived(const QByteArray& data);
|
||||||
|
void websocketTextReceived(const QString& text);
|
||||||
|
void websocketError(const QString& error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CommunicationManager(QObject* parent = nullptr);
|
||||||
|
~CommunicationManager();
|
||||||
|
|
||||||
|
// 内部初始化
|
||||||
|
void initHttpChannel();
|
||||||
|
void initWebSocketChannel();
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
ChannelConfig m_httpConfig;
|
||||||
|
ChannelConfig m_websocketConfig;
|
||||||
|
|
||||||
|
// 通道实例
|
||||||
|
QSharedPointer<HttpChannel> m_httpChannel;
|
||||||
|
QSharedPointer<WebSocketChannel> m_websocketChannel;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// DataProcessor.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMutex>
|
||||||
|
#include "export.hpp"
|
||||||
|
|
||||||
|
// 网络数据处理中心
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC DataProcessor : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static DataProcessor* instance();
|
||||||
|
|
||||||
|
// 处理数据
|
||||||
|
void processData(const QVariant& data,int conType = 0);
|
||||||
|
|
||||||
|
// 获取处理后的数据
|
||||||
|
QVariant getProcessedData(const QString& key) const;
|
||||||
|
|
||||||
|
// 清除所有数据
|
||||||
|
void clearAllData();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// 数据处理完成信号
|
||||||
|
void httpProcessed(const QString& sType,const QVariant& data);
|
||||||
|
void websocketProcessed(const QVariant& data);
|
||||||
|
private:
|
||||||
|
DataProcessor(QObject* parent = nullptr);
|
||||||
|
// 通用处理函数
|
||||||
|
void processJson(const QVariant& data,int conType = 0); //0http 1websocket
|
||||||
|
|
||||||
|
// 数据缓存
|
||||||
|
QMap<QString, QVariant> m_dataCache;
|
||||||
|
mutable QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// HttpChannel.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "baseChannel.h"
|
||||||
|
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC HttpChannel : public BaseChannel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HttpChannel(const ChannelConfig& config, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
bool connect() override;
|
||||||
|
bool disconnect() override;
|
||||||
|
bool isConnected() const override;
|
||||||
|
bool send(const QByteArray& data) override;
|
||||||
|
|
||||||
|
// HTTP方法
|
||||||
|
bool get(const QString& path = "");
|
||||||
|
bool post(const QByteArray& data, const QString& path = "");
|
||||||
|
bool put(const QByteArray& data, const QString& path = "");
|
||||||
|
bool deleteResource(const QString& path = "");
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
void setBasicAuth(const QString& username, const QString& password);
|
||||||
|
void setHeader(const QString& name, const QString& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_username;
|
||||||
|
QString m_password;
|
||||||
|
QMap<QString, QString> m_headers;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// uiCommunicationBus.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "export.hpp"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
// UI通信总线
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC UiCommunicationBus : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static UiCommunicationBus* instance();
|
||||||
|
|
||||||
|
// 发送HTTP请求
|
||||||
|
void sendHttpRequest(const QString& endpoint, const QVariant& data = QVariant());
|
||||||
|
|
||||||
|
// 发送HTTP请求(无回复)
|
||||||
|
void sendHttpRequestNoReply(const QString& endpoint, const QVariant& data = QVariant());
|
||||||
|
|
||||||
|
// 向UI发送数据
|
||||||
|
void sendToUi(const QString& uiId, const QString& action, const QVariant& data);
|
||||||
|
|
||||||
|
// 广播到所有UI
|
||||||
|
void broadcastToUis(const QString& action, const QVariant& data);
|
||||||
|
|
||||||
|
// 注册/注销UI
|
||||||
|
void registerUi(const QString& uiId, QObject* uiObject);
|
||||||
|
void unregisterUi(const QString& uiId);
|
||||||
|
signals:
|
||||||
|
void httpDataProcessed(const QString& type,const QVariant& data); //发送分拣过的数据给外部
|
||||||
|
void websocketDataProcessed(const QVariant& data);
|
||||||
|
private:
|
||||||
|
UiCommunicationBus(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
// 处理HTTP响应
|
||||||
|
void onHttpDataReceived(const QByteArray& data);
|
||||||
|
|
||||||
|
// 处理WebSocket数据
|
||||||
|
void onWebSocketDataReceived(const QByteArray& data);
|
||||||
|
|
||||||
|
// UI注册表
|
||||||
|
QMap<QString, QObject*> m_uiObjects;
|
||||||
|
mutable QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// WebSocketChannel.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "baseChannel.h"
|
||||||
|
#include <QWebSocket>
|
||||||
|
|
||||||
|
class DIAGRAM_DESIGNER_PUBLIC WebSocketChannel : public BaseChannel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct WebSocketConfig {
|
||||||
|
int heartbeatInterval = 30000;
|
||||||
|
};
|
||||||
|
|
||||||
|
WebSocketChannel(const ChannelConfig& config, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
bool connect() override;
|
||||||
|
bool disconnect() override;
|
||||||
|
bool isConnected() const override;
|
||||||
|
bool send(const QByteArray& data) override;
|
||||||
|
|
||||||
|
bool sendText(const QString& text);
|
||||||
|
void setWebSocketConfig(const WebSocketConfig& config);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void textMessageReceived(const QString& message);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onConnected();
|
||||||
|
void onDisconnected();
|
||||||
|
void onTextMessageReceived(const QString& message);
|
||||||
|
void onBinaryMessageReceived(const QByteArray& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWebSocket* m_webSocket = nullptr;
|
||||||
|
WebSocketConfig m_wsConfig;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
#include "baseChannel.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
BaseChannel::BaseChannel(const ChannelConfig& config, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_config(config)
|
||||||
|
, m_reconnectTimer(new QTimer(this))
|
||||||
|
{
|
||||||
|
m_reconnectTimer->setSingleShot(true);
|
||||||
|
QObject::connect(m_reconnectTimer,&QTimer::timeout, this, &BaseChannel::onReconnectTimeout);
|
||||||
|
|
||||||
|
qDebug() << "BaseChannel created:" << m_config.channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseChannel::~BaseChannel()
|
||||||
|
{
|
||||||
|
stopReconnectTimer();
|
||||||
|
qDebug() << "BaseChannel destroyed:" << m_config.channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseChannel::setAutoReconnect(bool enable)
|
||||||
|
{
|
||||||
|
m_autoReconnect = enable;
|
||||||
|
if (!enable) {
|
||||||
|
stopReconnectTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseChannel::startReconnectTimer()
|
||||||
|
{
|
||||||
|
if (m_autoReconnect && m_reconnectCount < m_config.maxRetries) {
|
||||||
|
int delay = m_config.reconnectInterval * (1 << m_reconnectCount); // 指数退避
|
||||||
|
m_reconnectTimer->start(qMin(delay, 30000)); // 最大30秒
|
||||||
|
m_reconnectCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseChannel::stopReconnectTimer()
|
||||||
|
{
|
||||||
|
m_reconnectTimer->stop();
|
||||||
|
m_reconnectCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseChannel::reconnect()
|
||||||
|
{
|
||||||
|
if (m_autoReconnect) {
|
||||||
|
disconnect();
|
||||||
|
QTimer::singleShot(100, this, [this]() {
|
||||||
|
connect();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseChannel::onReconnectTimeout()
|
||||||
|
{
|
||||||
|
if (m_autoReconnect) {
|
||||||
|
qDebug() << "Reconnecting channel" << m_config.channelId
|
||||||
|
<< "attempt" << m_reconnectCount << "/" << m_config.maxRetries;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray BaseChannel::generateMessageId() const
|
||||||
|
{
|
||||||
|
QString id = QString("%1_%2")
|
||||||
|
.arg(m_config.channelId)
|
||||||
|
.arg(QDateTime::currentMSecsSinceEpoch());
|
||||||
|
return QCryptographicHash::hash(id.toUtf8(), QCryptographicHash::Md5).toHex();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 BaseChannel::currentTimestamp() const
|
||||||
|
{
|
||||||
|
return QDateTime::currentMSecsSinceEpoch();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
// CommunicationManager.cpp
|
||||||
|
#include "communicationManager.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
CommunicationManager* CommunicationManager::instance()
|
||||||
|
{
|
||||||
|
static CommunicationManager* instance = nullptr;
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (!instance) {
|
||||||
|
instance = new CommunicationManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommunicationManager::CommunicationManager(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
// 设置默认配置
|
||||||
|
m_httpConfig.id = "http_channel";
|
||||||
|
m_httpConfig.name = "HTTP通道";
|
||||||
|
m_httpConfig.endpoint = "http://localhost:8080";
|
||||||
|
|
||||||
|
m_websocketConfig.id = "websocket_channel";
|
||||||
|
m_websocketConfig.name = "WebSocket通道";
|
||||||
|
m_websocketConfig.endpoint = "ws://localhost:8888/ws";
|
||||||
|
}
|
||||||
|
|
||||||
|
CommunicationManager::~CommunicationManager()
|
||||||
|
{
|
||||||
|
disconnectHttp();
|
||||||
|
disconnectWebSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::initialize()
|
||||||
|
{
|
||||||
|
// 初始化HTTP通道
|
||||||
|
initHttpChannel();
|
||||||
|
|
||||||
|
// 初始化WebSocket通道
|
||||||
|
initWebSocketChannel();
|
||||||
|
|
||||||
|
qInfo() << "CommunicationManager initialized";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommunicationManager::initHttpChannel()
|
||||||
|
{
|
||||||
|
if (m_httpChannel) {
|
||||||
|
m_httpChannel->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTP通道
|
||||||
|
HttpChannel::ChannelConfig httpConfig;
|
||||||
|
httpConfig.endpoint = QUrl(m_httpConfig.endpoint);
|
||||||
|
httpConfig.timeout = m_httpConfig.timeout;
|
||||||
|
|
||||||
|
m_httpChannel.reset(new HttpChannel(httpConfig));
|
||||||
|
|
||||||
|
// 设置认证
|
||||||
|
if (!m_httpConfig.username.isEmpty() && !m_httpConfig.password.isEmpty()) {
|
||||||
|
m_httpChannel->setBasicAuth(m_httpConfig.username, m_httpConfig.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置HTTP头
|
||||||
|
for (auto it = m_httpConfig.headers.begin(); it != m_httpConfig.headers.end(); ++it) {
|
||||||
|
m_httpChannel->setHeader(it.key(), it.value().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接信号
|
||||||
|
connect(m_httpChannel.data(), &HttpChannel::connected,
|
||||||
|
this, &CommunicationManager::httpConnected);
|
||||||
|
connect(m_httpChannel.data(), &HttpChannel::disconnected,
|
||||||
|
this, &CommunicationManager::httpDisconnected);
|
||||||
|
connect(m_httpChannel.data(), &HttpChannel::dataReceived,
|
||||||
|
this, &CommunicationManager::httpDataReceived);
|
||||||
|
connect(m_httpChannel.data(), &HttpChannel::errorOccurred,
|
||||||
|
this, &CommunicationManager::httpError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommunicationManager::initWebSocketChannel()
|
||||||
|
{
|
||||||
|
if (m_websocketChannel) {
|
||||||
|
m_websocketChannel->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建WebSocket通道
|
||||||
|
WebSocketChannel::ChannelConfig wsConfig;
|
||||||
|
wsConfig.endpoint = QUrl(m_websocketConfig.endpoint);
|
||||||
|
wsConfig.timeout = m_websocketConfig.timeout;
|
||||||
|
|
||||||
|
WebSocketChannel::WebSocketConfig websocketConfig;
|
||||||
|
websocketConfig.heartbeatInterval = m_websocketConfig.heartbeatInterval;
|
||||||
|
|
||||||
|
m_websocketChannel.reset(new WebSocketChannel(wsConfig));
|
||||||
|
m_websocketChannel->setWebSocketConfig(websocketConfig);
|
||||||
|
|
||||||
|
// 连接信号
|
||||||
|
connect(m_websocketChannel.data(), &WebSocketChannel::connected,
|
||||||
|
this, &CommunicationManager::websocketConnected);
|
||||||
|
connect(m_websocketChannel.data(), &WebSocketChannel::disconnected,
|
||||||
|
this, &CommunicationManager::websocketDisconnected);
|
||||||
|
connect(m_websocketChannel.data(), &WebSocketChannel::dataReceived,
|
||||||
|
this, &CommunicationManager::websocketDataReceived);
|
||||||
|
connect(m_websocketChannel.data(), &WebSocketChannel::errorOccurred,
|
||||||
|
this, &CommunicationManager::websocketError);
|
||||||
|
connect(m_websocketChannel.data(), &WebSocketChannel::textMessageReceived,
|
||||||
|
this, &CommunicationManager::websocketTextReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::connectHttp()
|
||||||
|
{
|
||||||
|
if (!m_httpChannel) {
|
||||||
|
qWarning() << "HTTP channel not initialized";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_httpChannel->isConnected()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_httpChannel->connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::disconnectHttp()
|
||||||
|
{
|
||||||
|
if (!m_httpChannel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_httpChannel->isConnected()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_httpChannel->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::sendHttpRequest(const QString& path,
|
||||||
|
const QByteArray& data,
|
||||||
|
const QString& method)
|
||||||
|
{
|
||||||
|
if (!m_httpChannel || !m_httpChannel->isConnected()) {
|
||||||
|
qWarning() << "HTTP channel not connected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method == "GET") {
|
||||||
|
return m_httpChannel->get(path);
|
||||||
|
} else if (method == "POST") {
|
||||||
|
return m_httpChannel->post(data, path);
|
||||||
|
} else if (method == "PUT") {
|
||||||
|
return m_httpChannel->put(data, path);
|
||||||
|
} else if (method == "DELETE") {
|
||||||
|
return m_httpChannel->deleteResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "Unsupported HTTP method:" << method;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::connectWebSocket()
|
||||||
|
{
|
||||||
|
if (!m_websocketChannel) {
|
||||||
|
qWarning() << "WebSocket channel not initialized";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_websocketChannel->isConnected()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_websocketChannel->connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::disconnectWebSocket()
|
||||||
|
{
|
||||||
|
if (!m_websocketChannel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_websocketChannel->isConnected()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_websocketChannel->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::sendWebSocketMessage(const QByteArray& data)
|
||||||
|
{
|
||||||
|
if (!m_websocketChannel || !m_websocketChannel->isConnected()) {
|
||||||
|
qWarning() << "WebSocket channel not connected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_websocketChannel->send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::sendWebSocketText(const QString& text)
|
||||||
|
{
|
||||||
|
if (!m_websocketChannel || !m_websocketChannel->isConnected()) {
|
||||||
|
qWarning() << "WebSocket channel not connected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_websocketChannel->sendText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::isHttpConnected() const
|
||||||
|
{
|
||||||
|
return m_httpChannel && m_httpChannel->isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommunicationManager::isWebSocketConnected() const
|
||||||
|
{
|
||||||
|
return m_websocketChannel && m_websocketChannel->isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig CommunicationManager::getHttpConfig() const
|
||||||
|
{
|
||||||
|
return m_httpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig CommunicationManager::getWebSocketConfig() const
|
||||||
|
{
|
||||||
|
return m_websocketConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommunicationManager::updateHttpConfig(const ChannelConfig& config)
|
||||||
|
{
|
||||||
|
bool reconnect = false;
|
||||||
|
|
||||||
|
if (m_httpConfig.endpoint != config.endpoint) {
|
||||||
|
// 端点变化,需要重新初始化
|
||||||
|
reconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_httpConfig = config;
|
||||||
|
initHttpChannel();
|
||||||
|
|
||||||
|
if (reconnect && config.autoConnect) {
|
||||||
|
connectHttp();
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "HTTP config updated";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommunicationManager::updateWebSocketConfig(const ChannelConfig& config)
|
||||||
|
{
|
||||||
|
bool reconnect = false;
|
||||||
|
|
||||||
|
if (m_websocketConfig.endpoint != config.endpoint) {
|
||||||
|
reconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_websocketConfig = config;
|
||||||
|
initWebSocketChannel();
|
||||||
|
|
||||||
|
if (reconnect && config.autoConnect) {
|
||||||
|
connectWebSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "WebSocket config updated";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
// ConfigManager.cpp
|
||||||
|
#include "configManager.h"
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
ConfigManager* ConfigManager::instance()
|
||||||
|
{
|
||||||
|
static ConfigManager* instance = nullptr;
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (!instance) {
|
||||||
|
instance = new ConfigManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager::ConfigManager(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
// 设置默认配置路径
|
||||||
|
QString appDir = QCoreApplication::applicationDirPath();
|
||||||
|
m_configFile = appDir + "/config.json";
|
||||||
|
|
||||||
|
qDebug() << "ConfigManager initialized, config file:" << m_configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::loadConfig(const QString& configFile)
|
||||||
|
{
|
||||||
|
if (!configFile.isEmpty()) {
|
||||||
|
m_configFile = configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(m_configFile);
|
||||||
|
|
||||||
|
// 如果文件不存在,创建默认配置
|
||||||
|
if (!file.exists()) {
|
||||||
|
qWarning() << "Config file not found, creating default config:" << m_configFile;
|
||||||
|
return createDefaultConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
qWarning() << "Failed to open config file:" << m_configFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray jsonData = file.readAll();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "JSON parse error:" << error.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doc.isObject()) {
|
||||||
|
qWarning() << "Config is not a JSON object";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap root = doc.object().toVariantMap();
|
||||||
|
|
||||||
|
// 加载HTTP配置
|
||||||
|
if (root.contains("http")) {
|
||||||
|
m_httpConfig = ChannelConfig::fromMap(root["http"].toMap());
|
||||||
|
} else {
|
||||||
|
qWarning() << "Config missing 'http' section, creating default";
|
||||||
|
m_httpConfig = getDefaultHttpConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载WebSocket配置
|
||||||
|
if (root.contains("websocket")) {
|
||||||
|
m_websocketConfig = ChannelConfig::fromMap(root["websocket"].toMap());
|
||||||
|
} else {
|
||||||
|
qWarning() << "Config missing 'websocket' section, creating default";
|
||||||
|
m_websocketConfig = getDefaultWebSocketConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "Config loaded from:" << m_configFile;
|
||||||
|
qInfo() << "HTTP endpoint:" << m_httpConfig.endpoint;
|
||||||
|
qInfo() << "WebSocket endpoint:" << m_websocketConfig.endpoint;
|
||||||
|
|
||||||
|
emit configLoaded();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::saveConfig()
|
||||||
|
{
|
||||||
|
// 确保目录存在
|
||||||
|
QFileInfo fileInfo(m_configFile);
|
||||||
|
QDir dir = fileInfo.dir();
|
||||||
|
|
||||||
|
if (!dir.exists()) {
|
||||||
|
if (!dir.mkpath(".")) {
|
||||||
|
qCritical() << "Failed to create config directory:" << dir.path();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap root = {
|
||||||
|
{"http", m_httpConfig.toMap()},
|
||||||
|
{"websocket", m_websocketConfig.toMap()},
|
||||||
|
{"lastSaved", QDateTime::currentDateTime().toString(Qt::ISODate)}
|
||||||
|
};
|
||||||
|
|
||||||
|
QFile file(m_configFile);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
qCritical() << "Failed to open config file for writing:" << m_configFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument doc = QJsonDocument::fromVariant(root);
|
||||||
|
file.write(doc.toJson(QJsonDocument::Indented));
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
qInfo() << "Config saved to:" << m_configFile;
|
||||||
|
emit configSaved();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::createDefaultConfig()
|
||||||
|
{
|
||||||
|
// 设置默认配置
|
||||||
|
m_httpConfig = getDefaultHttpConfig();
|
||||||
|
m_websocketConfig = getDefaultWebSocketConfig();
|
||||||
|
|
||||||
|
// 保存默认配置
|
||||||
|
bool success = saveConfig();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
qInfo() << "Default config created at:" << m_configFile;
|
||||||
|
} else {
|
||||||
|
qCritical() << "Failed to create default config";
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig ConfigManager::getDefaultHttpConfig() const
|
||||||
|
{
|
||||||
|
ChannelConfig config;
|
||||||
|
|
||||||
|
config.id = "http_channel";
|
||||||
|
config.name = "SCADA数据接口";
|
||||||
|
config.endpoint = "http://192.168.1.100:8080/api";
|
||||||
|
config.timeout = 30000;
|
||||||
|
config.enabled = true;
|
||||||
|
config.autoConnect = true;
|
||||||
|
config.username = "";
|
||||||
|
config.password = "";
|
||||||
|
config.connected = false;
|
||||||
|
config.lastConnectTime = QDateTime();
|
||||||
|
config.errorCount = 0;
|
||||||
|
|
||||||
|
// 默认HTTP头
|
||||||
|
config.headers = QVariantMap{
|
||||||
|
{"Content-Type", "application/json"},
|
||||||
|
};
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig ConfigManager::getDefaultWebSocketConfig() const
|
||||||
|
{
|
||||||
|
ChannelConfig config;
|
||||||
|
|
||||||
|
config.id = "websocket_channel";
|
||||||
|
config.name = "实时数据推送";
|
||||||
|
config.endpoint = "ws://192.168.1.101:8888/ws";
|
||||||
|
config.timeout = 30000;
|
||||||
|
config.enabled = true;
|
||||||
|
config.autoConnect = false;
|
||||||
|
config.connected = false;
|
||||||
|
config.lastConnectTime = QDateTime();
|
||||||
|
config.errorCount = 0;
|
||||||
|
config.heartbeatInterval = 30000;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig ConfigManager::getHttpConfig() const
|
||||||
|
{
|
||||||
|
return m_httpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelConfig ConfigManager::getWebSocketConfig() const
|
||||||
|
{
|
||||||
|
return m_websocketConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigManager::setHttpConfig(const ChannelConfig& config)
|
||||||
|
{
|
||||||
|
m_httpConfig = config;
|
||||||
|
emit httpConfigChanged(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigManager::setWebSocketConfig(const ChannelConfig& config)
|
||||||
|
{
|
||||||
|
m_websocketConfig = config;
|
||||||
|
emit websocketConfigChanged(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ConfigManager::configFilePath() const
|
||||||
|
{
|
||||||
|
return m_configFile;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// DataProcessor.cpp
|
||||||
|
#include "dataProcessor.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
DataProcessor* DataProcessor::instance()
|
||||||
|
{
|
||||||
|
static DataProcessor* instance = nullptr;
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (!instance) {
|
||||||
|
instance = new DataProcessor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataProcessor::DataProcessor(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
qDebug() << "DataProcessor initialized";
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataProcessor::processData(const QVariant& data,int conType)
|
||||||
|
{
|
||||||
|
qDebug() << "处理数据_size:" << data.toString().size();
|
||||||
|
|
||||||
|
// 根据数据类型处理
|
||||||
|
processJson(data.toJsonObject(),conType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataProcessor::processJson( const QVariant& data,int conType)
|
||||||
|
{
|
||||||
|
QJsonObject dataObj = data.toJsonObject();
|
||||||
|
if(conType == 0){
|
||||||
|
if(dataObj.contains("client_id")){ //实时数据相关
|
||||||
|
emit httpProcessed("recommend",data);
|
||||||
|
}
|
||||||
|
else if(dataObj.contains("input")){
|
||||||
|
emit httpProcessed("subscriptions",data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(conType == 1){
|
||||||
|
if(dataObj.contains("targets")){ //实时数据相关
|
||||||
|
emit websocketProcessed(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dataObj.contains("client_id")){ //实时数据相关
|
||||||
|
/*QString clientId = dataObj.value("client_id").toString();
|
||||||
|
QJsonArray arrTarget = dataObj.value("targets").toArray();
|
||||||
|
for (const QJsonValue& value : arrTarget) {
|
||||||
|
QJsonObject obj = value.toObject();
|
||||||
|
QString targetId = obj["id"].toString();
|
||||||
|
QString sCode = obj["code"].toString();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
else if(dataObj.contains("input")){
|
||||||
|
/*QString input = dataObj.value("input").toString();
|
||||||
|
int offSet = dataObj.value("offset").toInt();
|
||||||
|
QJsonArray recommendedList = dataObj.value("recommended_list").toArray();
|
||||||
|
for(const QJsonValue& value : recommendedList){
|
||||||
|
QString content = value.toString();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
//QMutexLocker locker(&m_mutex);
|
||||||
|
//m_dataCache[dataType] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant DataProcessor::getProcessedData(const QString& key) const
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
return m_dataCache.value(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataProcessor::clearAllData()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
m_dataCache.clear();
|
||||||
|
qDebug() << "已清除所有处理数据";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
// HttpAdapter.cpp
|
||||||
|
#include "httpChannel.h"
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkProxy>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
HttpAdapter::HttpAdapter(const ChannelConfig& config, QObject* parent)
|
||||||
|
: CommunicationChannel(config, parent)
|
||||||
|
, m_networkManager(new QNetworkAccessManager(this))
|
||||||
|
{
|
||||||
|
// 配置SSL
|
||||||
|
if (m_config.sslConfig.isNull()) {
|
||||||
|
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
||||||
|
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
m_config.sslConfig = sslConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接信号
|
||||||
|
connect(m_networkManager, &QNetworkAccessManager::authenticationRequired,
|
||||||
|
this, &HttpAdapter::onAuthenticationRequired);
|
||||||
|
|
||||||
|
qDebug() << "HttpAdapter created for" << m_config.channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpAdapter::~HttpAdapter()
|
||||||
|
{
|
||||||
|
// 取消所有未完成的请求
|
||||||
|
for (auto reply : m_pendingRequests.keys()) {
|
||||||
|
reply->abort();
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
m_pendingRequests.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::connectToHost()
|
||||||
|
{
|
||||||
|
// HTTP协议无需建立持久连接,只需验证端点是否可达
|
||||||
|
if (m_config.endpoint.isEmpty() || !m_config.endpoint.isValid()) {
|
||||||
|
emit errorOccurred("Invalid endpoint URL: " + m_config.endpoint.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送一个测试请求验证连接
|
||||||
|
HttpRequest testRequest;
|
||||||
|
testRequest.method = GET;
|
||||||
|
|
||||||
|
QNetworkRequest request(m_config.endpoint);
|
||||||
|
request.setSslConfiguration(m_config.sslConfig);
|
||||||
|
request.setRawHeader("User-Agent", "PowerSCADA/1.0");
|
||||||
|
|
||||||
|
QNetworkReply* reply = m_networkManager->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished,
|
||||||
|
this, [this, reply]() {
|
||||||
|
onReplyFinished(reply);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_pendingRequests.insert(reply, testRequest);
|
||||||
|
|
||||||
|
// 设置超时
|
||||||
|
QTimer::singleShot(m_config.timeout, this, [this, reply]() {
|
||||||
|
if (reply && reply->isRunning()) {
|
||||||
|
reply->abort();
|
||||||
|
emit errorOccurred("Connection timeout");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
emit connected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::disconnectFromHost()
|
||||||
|
{
|
||||||
|
// 取消所有未完成的请求
|
||||||
|
for (auto reply : m_pendingRequests.keys()) {
|
||||||
|
reply->abort();
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
m_pendingRequests.clear();
|
||||||
|
|
||||||
|
emit disconnected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::sendData(const QByteArray& data)
|
||||||
|
{
|
||||||
|
HttpRequest request;
|
||||||
|
request.method = POST;
|
||||||
|
request.data = data;
|
||||||
|
request.contentType = "application/octet-stream";
|
||||||
|
|
||||||
|
return sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::isConnected() const
|
||||||
|
{
|
||||||
|
// HTTP是无状态协议,总是返回true表示可以发送请求
|
||||||
|
return m_config.endpoint.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::sendRequest(const HttpRequest& request)
|
||||||
|
{
|
||||||
|
if (!m_config.endpoint.isValid()) {
|
||||||
|
emit errorOccurred("Invalid endpoint URL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest networkRequest(m_config.endpoint);
|
||||||
|
networkRequest.setSslConfiguration(m_config.sslConfig);
|
||||||
|
networkRequest.setRawHeader("User-Agent", "PowerSCADA/1.0");
|
||||||
|
networkRequest.setRawHeader("Content-Type", request.contentType.toUtf8());
|
||||||
|
|
||||||
|
// 添加自定义头
|
||||||
|
for (auto it = request.headers.begin(); it != request.headers.end(); ++it) {
|
||||||
|
networkRequest.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply* reply = nullptr;
|
||||||
|
|
||||||
|
switch (request.method) {
|
||||||
|
case GET:
|
||||||
|
reply = m_networkManager->get(networkRequest);
|
||||||
|
break;
|
||||||
|
case POST:
|
||||||
|
reply = m_networkManager->post(networkRequest, request.data);
|
||||||
|
break;
|
||||||
|
case PUT:
|
||||||
|
reply = m_networkManager->put(networkRequest, request.data);
|
||||||
|
break;
|
||||||
|
case DELETE:
|
||||||
|
reply = m_networkManager->deleteResource(networkRequest);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
emit errorOccurred("Unsupported HTTP method");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
emit errorOccurred("Failed to create network request");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求超时
|
||||||
|
QTimer* timeoutTimer = new QTimer(this);
|
||||||
|
timeoutTimer->setSingleShot(true);
|
||||||
|
connect(timeoutTimer, &QTimer::timeout, this, [this, reply]() {
|
||||||
|
if (reply && reply->isRunning()) {
|
||||||
|
reply->abort();
|
||||||
|
emit errorOccurred("Request timeout");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
timeoutTimer->start(m_config.timeout);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, reply, timeoutTimer]() {
|
||||||
|
timeoutTimer->stop();
|
||||||
|
timeoutTimer->deleteLater();
|
||||||
|
onReplyFinished(reply);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_pendingRequests.insert(reply, request);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpAdapter::setAuthentication(const QString& username, const QString& password)
|
||||||
|
{
|
||||||
|
m_username = username;
|
||||||
|
m_password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpAdapter::setProxy(const QNetworkProxy& proxy)
|
||||||
|
{
|
||||||
|
m_networkManager->setProxy(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::readDataPoints(const QStringList& pointIds)
|
||||||
|
{
|
||||||
|
QJsonObject requestObj;
|
||||||
|
requestObj["command"] = "read";
|
||||||
|
requestObj["points"] = QJsonArray::fromStringList(pointIds);
|
||||||
|
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||||
|
|
||||||
|
HttpRequest request;
|
||||||
|
request.method = POST;
|
||||||
|
request.data = QJsonDocument(requestObj).toJson();
|
||||||
|
request.contentType = "application/json";
|
||||||
|
|
||||||
|
return sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::writeDataPoint(const QString& pointId, const QVariant& value)
|
||||||
|
{
|
||||||
|
QJsonObject requestObj;
|
||||||
|
requestObj["command"] = "write";
|
||||||
|
requestObj["point"] = pointId;
|
||||||
|
requestObj["value"] = QJsonValue::fromVariant(value);
|
||||||
|
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||||
|
|
||||||
|
HttpRequest request;
|
||||||
|
request.method = POST;
|
||||||
|
request.data = QJsonDocument(requestObj).toJson();
|
||||||
|
request.contentType = "application/json";
|
||||||
|
|
||||||
|
return sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpAdapter::sendControlCommand(const QString& deviceId, int command, const QVariant& param)
|
||||||
|
{
|
||||||
|
QJsonObject requestObj;
|
||||||
|
requestObj["command"] = "control";
|
||||||
|
requestObj["device"] = deviceId;
|
||||||
|
requestObj["cmd"] = command;
|
||||||
|
requestObj["param"] = QJsonValue::fromVariant(param);
|
||||||
|
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||||
|
|
||||||
|
HttpRequest request;
|
||||||
|
request.method = POST;
|
||||||
|
request.data = QJsonDocument(requestObj).toJson();
|
||||||
|
request.contentType = "application/json";
|
||||||
|
|
||||||
|
return sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpAdapter::onReplyFinished(QNetworkReply* reply)
|
||||||
|
{
|
||||||
|
if (!reply || !m_pendingRequests.contains(reply)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto request = m_pendingRequests.take(reply);
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
QString errorMsg = QString("HTTP error: %1 - %2")
|
||||||
|
.arg(reply->error())
|
||||||
|
.arg(reply->errorString());
|
||||||
|
emit errorOccurred(errorMsg);
|
||||||
|
} else {
|
||||||
|
QByteArray responseData = reply->readAll();
|
||||||
|
emit dataReceived(responseData);
|
||||||
|
|
||||||
|
// 记录日志
|
||||||
|
qDebug() << "HTTP response received:" << reply->url().toString()
|
||||||
|
<< "Status:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()
|
||||||
|
<< "Size:" << responseData.size() << "bytes";
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpAdapter::onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator)
|
||||||
|
{
|
||||||
|
if (!m_username.isEmpty() && !m_password.isEmpty()) {
|
||||||
|
authenticator->setUser(m_username);
|
||||||
|
authenticator->setPassword(m_password);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Authentication required but no credentials provided";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
// HttpChannel.cpp
|
||||||
|
#include "httpChannel.h"
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QAuthenticator>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
HttpChannel::HttpChannel(const ChannelConfig& config, QObject* parent)
|
||||||
|
: BaseChannel(config, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::connect()
|
||||||
|
{
|
||||||
|
// HTTP无需建立持久连接
|
||||||
|
emit connected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::disconnect()
|
||||||
|
{
|
||||||
|
// HTTP无需断开持久连接
|
||||||
|
emit disconnected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::isConnected() const
|
||||||
|
{
|
||||||
|
return m_config.endpoint.isValid(); // 只要端点有效就认为"可连接"
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::send(const QByteArray& data)
|
||||||
|
{
|
||||||
|
return post(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::get(const QString& path)
|
||||||
|
{
|
||||||
|
if (!m_config.endpoint.isValid()) {
|
||||||
|
emit errorOccurred("Invalid endpoint");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url = m_config.endpoint;
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
url.setPath(url.path() + "/" + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
|
||||||
|
|
||||||
|
QObject::connect(manager, &QNetworkAccessManager::authenticationRequired,
|
||||||
|
[this](QNetworkReply* reply, QAuthenticator* authenticator) {
|
||||||
|
if (!m_username.isEmpty() && !m_password.isEmpty()) {
|
||||||
|
authenticator->setUser(m_username);
|
||||||
|
authenticator->setPassword(m_password);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
|
||||||
|
// 设置头
|
||||||
|
for (auto it = m_headers.begin(); it != m_headers.end(); ++it) {
|
||||||
|
request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply* reply = manager->get(request);
|
||||||
|
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished, [this, reply, manager]() {
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
emit dataReceived(data);
|
||||||
|
} else {
|
||||||
|
emit errorOccurred(reply->errorString());
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
manager->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::post(const QByteArray& data, const QString& path)
|
||||||
|
{
|
||||||
|
if (!m_config.endpoint.isValid()) {
|
||||||
|
emit errorOccurred("Invalid endpoint");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url = m_config.endpoint;
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
url.setPath(url.path() + "/" + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
for (auto it = m_headers.begin(); it != m_headers.end(); ++it) {
|
||||||
|
request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply* reply = manager->post(request, data);
|
||||||
|
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished,this,[this, reply, manager]() {
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
emit dataReceived(data);
|
||||||
|
} else {
|
||||||
|
emit errorOccurred(reply->errorString());
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
manager->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::put(const QByteArray& data, const QString& path)
|
||||||
|
{
|
||||||
|
// 类似post的实现
|
||||||
|
return post(data, path); // 简化处理
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpChannel::deleteResource(const QString& path)
|
||||||
|
{
|
||||||
|
// 类似get的实现
|
||||||
|
return get(path); // 简化处理
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpChannel::setBasicAuth(const QString& username, const QString& password)
|
||||||
|
{
|
||||||
|
m_username = username;
|
||||||
|
m_password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpChannel::setHeader(const QString& name, const QString& value)
|
||||||
|
{
|
||||||
|
m_headers[name] = value;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
// UiCommunicationBus.cpp
|
||||||
|
#include "uiCommunicationBus.h"
|
||||||
|
#include "communicationManager.h"
|
||||||
|
#include "dataProcessor.h"
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
UiCommunicationBus* UiCommunicationBus::instance()
|
||||||
|
{
|
||||||
|
static UiCommunicationBus* instance = nullptr;
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (!instance) {
|
||||||
|
instance = new UiCommunicationBus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
UiCommunicationBus::UiCommunicationBus(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
// 连接到CommunicationManager
|
||||||
|
CommunicationManager* comm = CommunicationManager::instance();
|
||||||
|
|
||||||
|
// 连接HTTP信号
|
||||||
|
connect(comm, &CommunicationManager::httpDataReceived,
|
||||||
|
this, &UiCommunicationBus::onHttpDataReceived);
|
||||||
|
|
||||||
|
// 连接WebSocket信号
|
||||||
|
connect(comm, &CommunicationManager::websocketDataReceived,
|
||||||
|
this, &UiCommunicationBus::onWebSocketDataReceived);
|
||||||
|
|
||||||
|
// 连接DataProcessor信号
|
||||||
|
DataProcessor* processor = DataProcessor::instance();
|
||||||
|
connect(processor, &DataProcessor::httpProcessed,
|
||||||
|
this, [this](const QString& dataType, const QVariant& data) {
|
||||||
|
if(dataType == "recommend"){
|
||||||
|
// 推荐列表请求将数据分发回订阅ui
|
||||||
|
broadcastToUis(dataType, data);
|
||||||
|
}
|
||||||
|
emit httpDataProcessed(dataType,data);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(processor, &DataProcessor::websocketProcessed,
|
||||||
|
this, [this](const QVariant& data) {
|
||||||
|
emit websocketDataProcessed(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
qDebug() << "UiCommunicationBus initialized";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::sendHttpRequest(const QString& endpoint, const QVariant& data)
|
||||||
|
{
|
||||||
|
CommunicationManager* comm = CommunicationManager::instance();
|
||||||
|
|
||||||
|
QJsonDocument doc = QJsonDocument::fromVariant(data);
|
||||||
|
bool success = comm->sendHttpRequest(endpoint, doc.toJson());
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
qDebug() << "HTTP请求已发送:" << endpoint;
|
||||||
|
} else {
|
||||||
|
qWarning() << "HTTP请求发送失败:" << endpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::sendHttpRequestNoReply(const QString& endpoint, const QVariant& data)
|
||||||
|
{
|
||||||
|
CommunicationManager* comm = CommunicationManager::instance();
|
||||||
|
|
||||||
|
QJsonDocument doc = QJsonDocument::fromVariant(data);
|
||||||
|
comm->sendHttpRequest(endpoint, doc.toJson());
|
||||||
|
|
||||||
|
qDebug() << "无回复HTTP请求已发送:" << endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::onHttpDataReceived(const QByteArray& data)
|
||||||
|
{
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "HTTP响应解析失败:" << error.errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant response = doc.toVariant();
|
||||||
|
|
||||||
|
if (response.typeId() == QMetaType::QVariantMap) {
|
||||||
|
QVariantMap responseMap = response.toMap();
|
||||||
|
DataProcessor* processor = DataProcessor::instance();
|
||||||
|
|
||||||
|
QString state = responseMap.value("msg").toString();
|
||||||
|
if(state == "success"){
|
||||||
|
if(responseMap.contains("payload")){
|
||||||
|
processor->processData(responseMap.value("payload"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "HTTP响应已处理";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::onWebSocketDataReceived(const QByteArray& data)
|
||||||
|
{
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "WebSocket数据解析失败:" << error.errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant response = doc.toVariant();
|
||||||
|
|
||||||
|
if (response.typeId() == QMetaType::QVariantMap) {
|
||||||
|
QVariantMap responseMap = response.toMap();
|
||||||
|
DataProcessor* processor = DataProcessor::instance();
|
||||||
|
|
||||||
|
QString state = responseMap.value("msg").toString();
|
||||||
|
if(state == "success"){
|
||||||
|
if(responseMap.contains("payload")){
|
||||||
|
processor->processData(responseMap.value("payload"),1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "WebSocket数据已处理";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::sendToUi(const QString& uiId, const QString& action, const QVariant& data)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
if (!m_uiObjects.contains(uiId)) {
|
||||||
|
qWarning() << "UI未注册:" << uiId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* uiObject = m_uiObjects[uiId];
|
||||||
|
|
||||||
|
// 尝试调用通用的消息处理槽
|
||||||
|
bool success = QMetaObject::invokeMethod(uiObject, "onMessage",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
Q_ARG(QString, action),
|
||||||
|
Q_ARG(QVariant, data));
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
qWarning() << "调用UI消息处理失败:" << uiId << "action:" << action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::broadcastToUis(const QString& action, const QVariant& data)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
for (auto it = m_uiObjects.begin(); it != m_uiObjects.end(); ++it) {
|
||||||
|
QObject* uiObject = it.value();
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(uiObject, "onMessage",
|
||||||
|
Q_ARG(QString, action),
|
||||||
|
Q_ARG(QVariant, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "消息广播:" << action << "接收者:" << m_uiObjects.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::registerUi(const QString& uiId, QObject* uiObject)
|
||||||
|
{
|
||||||
|
if (uiId.isEmpty() || !uiObject) {
|
||||||
|
qWarning() << "注册UI失败: 参数无效";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
m_uiObjects[uiId] = uiObject;
|
||||||
|
qDebug() << "UI已注册:" << uiId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiCommunicationBus::unregisterUi(const QString& uiId)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
m_uiObjects.remove(uiId);
|
||||||
|
qDebug() << "UI已注销:" << uiId;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
// WebSocketChannel.cpp
|
||||||
|
#include "webSocketChannel.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
WebSocketChannel::WebSocketChannel(const ChannelConfig& config, QObject* parent)
|
||||||
|
: BaseChannel(config, parent)
|
||||||
|
, m_webSocket(new QWebSocket)
|
||||||
|
{
|
||||||
|
QObject::connect(m_webSocket, &QWebSocket::connected,
|
||||||
|
this, &WebSocketChannel::onConnected);
|
||||||
|
QObject::connect(m_webSocket, &QWebSocket::disconnected,
|
||||||
|
this, &WebSocketChannel::onDisconnected);
|
||||||
|
QObject::connect(m_webSocket, &QWebSocket::textMessageReceived,
|
||||||
|
this, &WebSocketChannel::onTextMessageReceived);
|
||||||
|
QObject::connect(m_webSocket, &QWebSocket::binaryMessageReceived,
|
||||||
|
this, &WebSocketChannel::onBinaryMessageReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketChannel::connect()
|
||||||
|
{
|
||||||
|
if (m_webSocket->state() == QAbstractSocket::ConnectedState) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_config.endpoint.isValid()) {
|
||||||
|
emit errorOccurred("Invalid endpoint");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_webSocket->open(m_config.endpoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketChannel::disconnect()
|
||||||
|
{
|
||||||
|
if (m_webSocket->state() != QAbstractSocket::UnconnectedState) {
|
||||||
|
m_webSocket->close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketChannel::isConnected() const
|
||||||
|
{
|
||||||
|
return m_webSocket->state() == QAbstractSocket::ConnectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketChannel::send(const QByteArray& data)
|
||||||
|
{
|
||||||
|
if (!isConnected()) {
|
||||||
|
emit errorOccurred("WebSocket not connected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 sent = m_webSocket->sendBinaryMessage(data);
|
||||||
|
return sent == data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketChannel::sendText(const QString& text)
|
||||||
|
{
|
||||||
|
if (!isConnected()) {
|
||||||
|
emit errorOccurred("WebSocket not connected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 sent = m_webSocket->sendTextMessage(text);
|
||||||
|
return sent == text.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketChannel::setWebSocketConfig(const WebSocketConfig& config)
|
||||||
|
{
|
||||||
|
m_wsConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketChannel::onConnected()
|
||||||
|
{
|
||||||
|
emit connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketChannel::onDisconnected()
|
||||||
|
{
|
||||||
|
emit disconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketChannel::onTextMessageReceived(const QString& message)
|
||||||
|
{
|
||||||
|
emit textMessageReceived(message);
|
||||||
|
emit dataReceived(message.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketChannel::onBinaryMessageReceived(const QByteArray& message)
|
||||||
|
{
|
||||||
|
emit dataReceived(message);
|
||||||
|
}
|
||||||
|
|
@ -214,6 +214,9 @@ void CMainWindow::initializeAction()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QAction* settingAct = ui->menuSetting->addAction(QString::fromWCharArray(L"网络设置"));
|
||||||
|
connect(settingAct,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onSignal_openNetSetting);
|
||||||
|
|
||||||
QAction* testAct = ui->menuTest->addAction(QString::fromWCharArray(L"生成测试基模"));
|
QAction* testAct = ui->menuTest->addAction(QString::fromWCharArray(L"生成测试基模"));
|
||||||
connect(testAct,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onCreateTestBaseModelDiagram);
|
connect(testAct,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onCreateTestBaseModelDiagram);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,16 @@
|
||||||
<string>测试</string>
|
<string>测试</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuSetting">
|
||||||
|
<property name="title">
|
||||||
|
<string>设置</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuView"/>
|
<addaction name="menuView"/>
|
||||||
<addaction name="menuMode"/>
|
<addaction name="menuMode"/>
|
||||||
<addaction name="menuProject"/>
|
<addaction name="menuProject"/>
|
||||||
|
<addaction name="menuSetting"/>
|
||||||
<addaction name="menuTest"/>
|
<addaction name="menuTest"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="toolBar">
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue