# 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://github.com/zhangjiechina001/LIBSServer/assets/49397821/f24ad8c4-f8cc-41c7-af42-faa42350c701) - ![运行图](http://192.168.0.60/jiezhang/LIBSServer/blob/master/ReadMe/%E6%9E%B6%E6%9E%84%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.png) - 图片替换文本 - [思维导图](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模块思维导图(更新可能不及时,主要看一看定义的基类模块) ![LIBSServer软件架构](https://github.com/zhangjiechina001/LIBSServer/assets/49397821/2124a6fb-574b-4677-b1f8-ba76b5dc712b) ## 编码思考(软规范) 1. 每个模块需要配置相应的调试界面,方便现场调试 2. 开发和迭代过程中发现业务变化时,多对业务进行更深一层次的思考,及时重构,切忌一直以打补丁的方式进行业务迭代,否则维护过于困难 3. 在Qt平台上实践单元测试较少,现在更多的是模拟测试。测试的核心就是**快速验证**自己的代码逻辑,不要等到最后在现场摸奖 4. 之前是从C#转过来的,代码风格也是吸收了C#的优点,类似C#和C++的集合体,很多命名也是参考了《框架设计指南-构建可覅用的.NET库的约定、惯例与模式(第3版)》,微软大佬呕心沥血之作 5. 模块之间接口定义清晰,切忌出现神秘命名