# GSLIBSInsightEyeServerV2
**Repository Path**: zhang_jie_sc/gslibsinsight-eye-server-v2
## Basic Information
- **Project Name**: GSLIBSInsightEyeServerV2
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2025-07-16
- **Last Updated**: 2025-11-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# LIBSServer
- 
- 
-
- [思维导图](https://kdocs.cn/l/ctWzUO11RZzd)
*
## 1.主要功能
* 使用tcp/串口发送指令控制不同设备,可独立/配合服务端软件控制下游设备开始测量流程
* 每个设备具有独立调试界面,方便设备故障排除
* 实现多种通讯方式(modbus,zmq,tcp,串口),将通讯功能抽象为接口,方便通讯协议拓展
* 将软件按照抽象层测分为通讯层、设备层、指令层\控制层,使用*Manager单例读取Json配置文件实现实体的创建和管理,上层调用下层,使用基类提供功能,实现各模块充分解耦
## 2.历史版本
* v1.0
## 3.背景
之前LIBS系列产品软件数量过多,功能重复开发。现将LIBS主线业务抽出,在前人软件的基础上,充分使用C++语言的面向对象特性,开发出一款拓展性强,更易于使用的LIBS服务端控制软件,也是LIBS设备标准化的重要一步。本人学习C++时间尚短,软件设计和编码方面还有很多不足,欢迎各位同事指出。
## 4.结构
从下到上分别简述软件各模块的功能
### 4.1通讯层(Communication模块)
通过CommunicationManager读取通讯配置后创建对应的通讯实体,现已实现**modbus,zmq,tcp,串口**等通讯
- BaseCommunication:定义通讯参数配置、通讯连接、通讯连接状态查询等基本方法
```cpp
class BaseCommunication:public QObject
{
Q_OBJECT
public:
Q_INVOKABLE explicit BaseCommunication(QObject *parent = 0);
virtual void SetCommunicationParam(QString communicationParam);
virtual QString GetCommunicationParam();
virtual bool Connect();
virtual bool IsConnected();
virtual void SetName(QString name);
virtual QString Name();
virtual void Dispose();
virtual void OtherConfig(QJsonObject config);
virtual QDialog* GetConfigDialog();
signals:
protected:
QString _name;
QJsonObject _otherConfig;
QString _communicationParam;
public slots:
};
```
- BaseSendReply:定义SendReply()和SendNoReply()方法
```cpp
//定义发送接收模式对象的必要功能 请求恢复 请求无回复 数据接收
//客户端和服务端功能不一样 服务端只接受响应 客户端负责发送接收数据
class BaseSendReply:public BaseCommunication
{
Q_OBJECT
public:
Q_INVOKABLE explicit BaseSendReply(QObject *parent=nullptr);
public:
virtual bool SendReply(QByteArray sendBuff,QByteArray &receiveBuff);
virtual bool SendNoReply(QByteArray sendBuff);
signals:
void DataReceive(QByteArray recData);
// BaseCommunication interface
public:
bool Connect() override;
bool IsConnected() override;
private:
QTcpSocket *_socket=nullptr;
QString _name="";
QString _ipPort="";
QTimer* _timer=nullptr;
bool _autoConnect=false;
QDialog* _configDialog=nullptr;
// BaseCommunication interface
public:
QDialog *GetConfigDialog() override;
static QString HexToString(QByteArray data);
};
```
- BaseSubscriber:订阅者、发布者模式的基本方法
```cpp
class BaseSubscriber:public BaseCommunication
{
Q_OBJECT
public:
Q_INVOKABLE explicit BaseSubscriber(QObject *parent=0);
virtual bool Publish(QByteArray data);
signals:
void Receive(QByteArray data);
// BaseCommunication interface
public:
virtual QDialog *GetConfigDialog() override;
private:
QDialog *_configW=nullptr;
};
```
还有**BaseModbus**,定义了Mobus所需要的方法,分别实现了串口Modbus和TCPModbus。
### 4.2设备层
Device模块,通过DeviceManager读取配置后创建对应设备实体
- BaseDevice:通讯实体设置、设备参数设置设置、设备状态监控、停止、复位、设备状态变化信号
```cpp
class BaseDevice : public QObject
{
Q_OBJECT
public:
BaseDevice(QObject *parent=nullptr);
virtual QString Name();
virtual void Name(QString name);
virtual QString Type();
virtual void Type(QString type);
virtual QList Communication();
virtual void Communication(QList communication);
virtual void SetOtherConfig(QJsonObject config);
virtual QJsonObject OtherConfig();
virtual QWidget* GetConfigQWidget();
//在流程中止时,先停止,然后再复位
virtual bool Stop();
virtual bool Reset();
signals:
void StatusChanged(QJsonObject obj);
private:
QString _name;
QString _type;
protected:
QList _communications;
QJsonObject _otherConfig;
signals:
public slots:
};
```
定义了IO控制、光谱仪、激光器、电机驱动、温度传感器、距离传感器等设备基类。
### 4.3指令层(未完善)
Command模块,业务核心,通过CommandManager读取指令配置后创建对应指令实体,将总的流程分解为有机组合的小流程,从在对应Command实体中实现这些流程
- BaseComand:定义指令执行、指令配置、指令控制设备配置、中断异常触发
```cpp
class BaseCommand:public ICommand
{
public:
BaseCommand();
public:
protected:
QJsonObject _otherConfig;
QString _name;
QList _allDevices;
// ICommand interface
public:
virtual void Execute() override;
virtual QString GetName() override;
virtual void SetName(QString name) override;
virtual QString GetDescription() override;
virtual void SetConfig(QJsonObject obj) override;
virtual void SetDevices(QList devices) override;
};
```
### 4.4控制面板(未完善)
ControlPanel,负责对控制层命令启动。接收外来控制指令,UI控制、远程控制、客户端控制、其他控制等。
- BaseControlPanel
```cpp
//负责设备控制、状态反馈功能
//使用观察者模式实现控制面板和控制模块的解耦
class BaseControlPanel:public QObject
{
Q_OBJECT
public:
enum RunMode
{
Off=0x00,
Single=0x01,
Internal=0x02,
Continuous=0x03,
Ready=0x04
};
Q_ENUM(RunMode)
public:
BaseControlPanel();
virtual QString Name();
virtual void Name(QString name);
virtual void Execute();
virtual void Execute(QString cmd);
virtual void Stop();
virtual void Reset();
virtual void SetDevice(QList devices);
virtual void SetCommunication(QList comms);
virtual QDialog* GetConfigWidget();
signals:
//设置仪器状态
void SetStatus(RunMode mode);
public slots:
//仪器状态发生改变时触发改信号
void StatusChanged(QJsonObject obj);
protected:
QString _name;
QList _allDevices;
QList _allComms;
};
```
### 4.5控制层(未完善)
Control模块,业务核心。在CommandManager单例中获取对应的指令实体、可以将控制分为设备指令发送(瞬态)和等待(非瞬态),在等待中检查中断标志,为true时触发中断异常,实现设备运行中随时中断的需求,避免了大量状态码检查。
```cpp
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
void Execute();
void Execute(QString cmdName);
void Execute(ICommand* cmd);
void Execute(QList cmds);
void WaitForEnd();
QList GetAllCmdNames() const;
ICommand* GetCmd(QString name);
signals:
void ReportProgress(int progress);
void CmdIndexChanged(int currentIndex);
private:
bool _isRunning;
QList _allCmds;
// RunMode _runMode;
CommandManager *_cmdMgr=nullptr;
signals:
public slots:
};
```
**在等待中进行流程中断触发**:
```cpp
void WaitUtils::WaitMs(int time)
{
//多处调用displayProgress该变量且有的时true有的时false时会导致进度显示异常,想不通。。。
QElapsedTimer ela;
ela.start();
while (ela.elapsed() < time)
{
CheckIsRunning();
ProgressReport::Instance().ReportProgress(((double)ela.elapsed()/time)*100);
QCoreApplication::processEvents(QEventLoop::AllEvents, 300);
}
}
void WaitUtils::CheckIsRunning()
{
if(!_isRunning)
{
qDebug()<<"流程中止";
_isRunning=true;
throw QString("process stop!");
}
}
```
### 4.6模块思维导图(更新可能不及时,主要看一看定义的基类模块)

## 编码思考(软规范)
1. 每个模块需要配置相应的调试界面,方便现场调试
2. 开发和迭代过程中发现业务变化时,多对业务进行更深一层次的思考,及时重构,切忌一直以打补丁的方式进行业务迭代,否则维护过于困难
3. 在Qt平台上实践单元测试较少,现在更多的是模拟测试。测试的核心就是**快速验证**自己的代码逻辑,不要等到最后在现场摸奖
4. 之前是从C#转过来的,代码风格也是吸收了C#的优点,类似C#和C++的集合体,很多命名也是参考了《框架设计指南-构建可覅用的.NET库的约定、惯例与模式(第3版)》,微软大佬呕心沥血之作
5. 模块之间接口定义清晰,切忌出现神秘命名