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${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets Sql Xml REQUIRED Charts)
|
||||
find_package(Qt6 REQUIRED COMPONENTS SvgWidgets)
|
||||
find_package(Qt6 COMPONENTS Network REQUIRED)
|
||||
find_package(Qt6 COMPONENTS Network WebSockets REQUIRED)
|
||||
find_package(PostgreSQL REQUIRED)
|
||||
|
||||
|
||||
|
|
@ -158,8 +158,9 @@ set_target_properties(DiagramDesigner PROPERTIES
|
|||
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(diagramUtils)
|
||||
add_subdirectory(diagramCommunication)
|
||||
|
||||
file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin")
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
|
|||
include/projectIconSetting.h
|
||||
include/projectIconSelectionDlg.h
|
||||
include/projectDiagramNameInput.h
|
||||
include/diagramConnectSetting.h
|
||||
include/diagramEditor/editPanel.h
|
||||
include/diagramEditor/editView.h
|
||||
include/diagramEditor/editScene.h
|
||||
|
|
@ -112,6 +113,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
|
|||
include/util/scalingSelector.h
|
||||
include/util/selectorManager.h
|
||||
include/util/subMovingSelector.h
|
||||
include/instance/dataAccessor.h
|
||||
../common/include/httpInterface.h
|
||||
../common/include/tools.h
|
||||
../common/include/global.h
|
||||
|
|
@ -160,6 +162,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
|
|||
source/projectIconSetting.cpp
|
||||
source/projectIconSelectionDlg.cpp
|
||||
source/projectDiagramNameInput.cpp
|
||||
source/diagramConnectSetting.cpp
|
||||
source/diagramEditor/editPanel.cpp
|
||||
source/diagramEditor/editView.cpp
|
||||
source/diagramEditor/editScene.cpp
|
||||
|
|
@ -232,6 +235,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
|
|||
source/util/scalingSelector.cpp
|
||||
source/util/selectorManager.cpp
|
||||
source/util/subMovingSelector.cpp
|
||||
source/instance/dataAccessor.cpp
|
||||
../common/source/httpInterface.cpp
|
||||
../common/source/baseProperty.cpp
|
||||
../common/source/tools.cpp
|
||||
|
|
@ -263,6 +267,7 @@ set(UI_FILES
|
|||
ui/monitorDetailAttributeDlg.ui
|
||||
ui/monitorDisplaySettingDlg.ui
|
||||
ui/loadMonitorPageDlg.ui
|
||||
ui/diagramConnectSetting.ui
|
||||
)
|
||||
|
||||
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::Xml)
|
||||
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::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_link_libraries(diagramCavas PRIVATE diagramUtils)
|
||||
target_link_libraries(diagramCavas PRIVATE diagramCommunication)
|
||||
|
||||
target_compile_definitions(diagramCavas
|
||||
PUBLIC
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class EditBaseItem;
|
|||
class MonitorPanel;
|
||||
class CornerMonitorLauncher;
|
||||
class LoadMonitorPageDlg;
|
||||
class DiagramConnectSetting;
|
||||
|
||||
class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea
|
||||
{
|
||||
|
|
@ -64,6 +65,8 @@ public slots:
|
|||
void onSignal_deleteDiagram(DiagramInfo);
|
||||
void onSignal_selectDiagram(DiagramInfo);
|
||||
|
||||
void onSignal_openNetSetting(); //打开网络设置
|
||||
|
||||
void onCreateTestBaseModelDiagram(); //生成测试基模图
|
||||
/******************************生成组态***********************************/
|
||||
void onSignal_createEditPanel(QString,QUuid);
|
||||
|
|
@ -104,6 +107,7 @@ private:
|
|||
QString _curPage;
|
||||
CornerMonitorLauncher* _cornerButton; //简略菜单呼出按钮
|
||||
LoadMonitorPageDlg* _loadMonitorPageDlg;
|
||||
DiagramConnectSetting* _connectSetting;
|
||||
};
|
||||
|
||||
#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 "cornerMonitorLauncher.h"
|
||||
#include "loadMonitorPageDlg.h"
|
||||
#include "diagramConnectSetting.h"
|
||||
#include "diagramCommunication/include/communicationManager.h"
|
||||
#include "diagramCommunication/include/configManager.h"
|
||||
|
||||
DiagramCavas::DiagramCavas(QWidget *parent)
|
||||
: QMdiArea(parent)
|
||||
,_cornerButton(nullptr)
|
||||
,_loadMonitorPageDlg(nullptr)
|
||||
,_connectSetting(nullptr)
|
||||
{
|
||||
_pageIndex = 0;
|
||||
}
|
||||
|
|
@ -77,6 +81,19 @@ void DiagramCavas::initial()
|
|||
}
|
||||
});
|
||||
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)
|
||||
|
|
@ -432,6 +449,13 @@ void DiagramCavas::onSignal_selectDiagram(DiagramInfo info)
|
|||
}
|
||||
}
|
||||
|
||||
void DiagramCavas::onSignal_openNetSetting()
|
||||
{
|
||||
if(_connectSetting){
|
||||
_connectSetting->showDlg();
|
||||
}
|
||||
}
|
||||
|
||||
void DiagramCavas::removePanel(PowerEntity* pEntity)
|
||||
{
|
||||
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()
|
||||
{
|
||||
// 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()){
|
||||
return;
|
||||
}
|
||||
|
|
@ -217,22 +194,6 @@ void MonitorDisplaySettingDlg::onDeviceComboBoxChanged(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) {
|
||||
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"生成测试基模"));
|
||||
connect(testAct,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onCreateTestBaseModelDiagram);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,16 @@
|
|||
<string>测试</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuSetting">
|
||||
<property name="title">
|
||||
<string>设置</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuMode"/>
|
||||
<addaction name="menuProject"/>
|
||||
<addaction name="menuSetting"/>
|
||||
<addaction name="menuTest"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
|
|
|
|||
Loading…
Reference in New Issue