#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace HalconCpp; #include "opencv2/opencv.hpp" using namespace cv; class TOOL; class DllTool; // 默认的硬件组态页面名称 #define GROUP_NAME_HARDWARE ("硬件组态") // 默认的TaskManager的页面名称 #define GROUP_NAME_TASKMONITOR ("任务监控") // 默认的DebugView的页面名称 #define GROUP_NAME_LOGVIEW ("日志信息") // 系统内置的Event的分组名称 #define GROUP_NAME_SYSTEMEVENT ("SYSTEM_EVENT") // 内置的全局变量组名字 #define GROUP_NAME_SYSTEM ("System") // 内置的默认变量组名字 #define GROUP_NAME_DEFAULVALUE ("DefaultValue") // 硬件组态的工具分类 #define CATEGORY_TOOL_HARDWARE ("硬件工具") ////======================================================== //// //// ENUM //// ////======================================================== /// /// 管理系统中所有的枚举类型(逐步添加中,方便使用Q_ENUM管理) /// class VPEnum : public QObject { Q_OBJECT public: /// /// 线程的优先级 /// enum class PRIORITY : short { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, HighestPriority, TimeCriticalPriority, InheritPriority }; Q_ENUM(PRIORITY); /// /// Tool工作状态 /// enum class EXEC_STATUS : short { Wait, // 等待事件中 Busy, // 执行中 Done, // 执行完毕 StandBy // 就绪状态,表示工具尚未执行 }; Q_ENUM(EXEC_STATUS) /// /// Tool执行的返回值 /// enum class RETURN_VALUE : short { Success = 0, // 工具执行成功 Error, // 工具执行错误 Invalid, // 工具无效 或被禁用 Timeout, // 工具执行超时 Goto, // 返回跳转信号 Abort, // 2022-9-5 因为各种原因,放弃执行此工具 None // 无状态,表示工具尚未执行 }; Q_ENUM(RETURN_VALUE) /// /// 全局变量的读写模式(仅DB模式使用) /// enum class GVL_ACCESS_MODE : short { All, ReadOnly, WriteOnly }; Q_ENUM(GVL_ACCESS_MODE) }; // 基础模式中包括的类型数量 #define GVL_BASIC_TYPE_COUNT 5 // 标准模式中包括的类型数量 #define GVL_STANDARD_TYPE_COUNT 28 /// /// 数据类型定义 /// enum class VALUE_TYPE : short { Type_Bool = 0, //bool Type_Int, //int Type_Float, //float Type_Double, //double Type_String, //QString Type_StdString, //std::string Type_QImage, //QImage Type_Mat, //Mat Type_HTuple, //HTuple Type_HObject, //HObject Type_HImage, //HImage Type_ST_Pos, //HTuple_Pos Type_ST_HomMat2D, //HTuple_HomMat2D Type_ST_Point, //HTuple_Point Type_ST_Line, //HTuple_Line Type_ST_Circle, //HTuple_Circle Type_ST_Disp, //HTuple_Disp Type_ST_Window, //HTuple_Window Type_ST_Ncc_Modle, //HTuple_Ncc_Modle Type_ST_Shape_Modle, //HTuple_Shape_Modle Type_ST_Calibration, //HTuple_Calibration Type_ST_CamParam_PoseCalib, //HTuple_CamParam_PoseCalib Type_pIBaseCamera, //IBaseCamera* Type_pIpImage, //lpImage* Type_pISocket, //ISocket* Type_pArrayIn, //ArrayIn* Type_pArrayOut, //ArrayOut* Type_pArrayRobotPos, //ArrayRobotPos* Control_Base = 100, Control_Label, Control_Button, Control_CheckBox, Control_RadioBox, Control_Groupbox, Control_Image, Control_LineEdit, Control_Listbox, Control_ComboBox, Control_Value, Control_PieChart, Control_CustomPlot, Control_Table, Control_Result, Control_Widget, // Type_Event, // 2022-9-3 废弃,统一到接口的 INF_EVENT 类型中 Type_Tool, Type_Unknown }; /// /// 数据类型定义 /// 此处对应DataStructure.h中的 VALUE_TYPE 顺序,要确保双方顺序同步 /// const static QStringList valueString = { "bool", // 0 "int", // 1 "float", // 2 "double", // 3 "QString", // 4 "std::string", // 5 "QImage", // 6 "Mat", // 7 "HTuple", // 8 "HObject", // 9 "HImage", // 10 "HPos", // 11 "HTuple_HomMat2D", // 12 "HTuple_Point", // 13 "HTuple_Line", // 14 "HTuple_Circle", // 15 "HTuple_Disp", // 16 "HTuple_Window", // 17 "HTuple_Ncc_Modle", // 18 "HTuple_Shape_Modle", // 19 "HTuple_Calibration", // 20 "HTuple_CamParam_PoseCalib", // 21 "IBaseCamera*", // 22 "lpImage*", // 23 "ISocket*", // 24 "ArrayIn*", // 25 "ArrayOut*", // 26 "ArrayRobotPos*", // 27 // 28 "ControlBase", // 100 "QLabel", // 101 "QPushButton", // 102 "QCheckBox", // 103 "QRadioButton", // 104 "QGroupBox", // 105 "QImage", // 106 "QLineEdit", // 107 "QListWidget", // 108 "QComboBox", // 109 "ValueControl", // 110 "PieChart", // 111 "WaveChart", // 112 "TableControl", // 113 "Result", // 114 "QWidget", // 115 "QEvent", "Tool", "Unknown" }; /// /// 输入输出类型 /// enum class INF_DIRECTION : short { INF_DIR_IN = 1, // 输入接口 INF_DIR_OUT = 2, // 输出接口 INF_DIR_BOTH = 3, // 双向接口(全局变量) INF_DIR_UNKNOWN, }; /// /// 端口废弃类型 /// enum class INF_DISCARD : short { INF_DEFAULT = 0, // 默认值(未废弃,正常使用的端口) INF_MARK_DELETE = 1, // 接口被删除 INF_MARK_DISCARD = 2, // 接口被标记为废弃 INF_MARK_CHANGE = 3 // 接口被修改(常因为端口的类型被修改) }; /// /// 工具总体类型(工具、控件或者变量) /// enum class TOOL_TYPE : short { TOOL_TYPE_STANDARD, // 标准工具 TOOL_TYPE_PORT_INPUT, // 输入端口工具 TOOL_TYPE_PORT_OUTPUT, // 输出端口工具 TOOL_TYPE_GLOBAL_VARIABLE, // 全局变量 TOOL_TYPE_LOCAL_VARIABLE, // 局部变量 TOOL_TYPE_GOTO, // 跳转工具 TOOL_TYPE_COMMENT, // 2022-3-13,注释工具 TOOL_TYPE_PARALLEL, // 2022-4-18,并行计算工具 TOOL_TYPE_FORLOOP, // 2022-8-21,For循环工具 TOOL_TYPE_WAIT, // 2022-9-2,Wait工具 TOOL_TYPE_UNKNOWN }; /// /// 接口总体类型 /// enum class INF_TYPE : short { INF_TYPE_STANDARD, // 标准接口 INF_TYPE_VALUE, // 数值接口(全局变量,局部变量) INF_TYPE_CONTROL, // 控件接口 INF_TYPE_TOOL, // 2022-8-21 Tool接口,包括输入和输出两种 INF_TYPE_EVENT, // 2021-7-27 增加,Event类型接口 INF_TYPE_UNKNOWN }; /// /// 值的传递方式 /// enum class VALUE_PASS_MODE : short { PASS_BY_VALUE, PASS_BY_ADDRESS, PASS_BY_UNKNOWN }; /// /// Tool的运行模式 /// enum class TOOL_RUN_MODE : short { SINGLE_STEP, // 单步执行 STANDALONE, // 独立运行(仅运行本工具) SEQUENTIAL, // 顺序执行(任务中,或者ExecuteAll执行) IN_PARALLEL, // 在并行工具中执行 IN_FORLOOP // 在For工具中执行 }; /// /// Task的运行模式 /// enum class TASK_RUN_MODE : short { RUN_LOOP, // 循环执行 RUN_ONCE, // 单次执行 RUN_STOP // 退出执行 }; // 更新值的工作模式 enum class UPDATE_VALUE_MODE : short { MODE_FROM_TOOL, // 从Tool接口中更新 MODE_FROM_VARIABLE, // 从变量中读取 MODE_TO_VARIABLE // 写入到变量中 }; /// /// 2022-2-15增加,变量模式(局部变量统一为BASIC模式,全局变量分三种模式) /// enum class GVL_MODE : short { GVL_BASIC, // 基础模式(基础类型) GVL_STANDARD, // 标准模式(全类型) GVL_SYSTEM, // 系统类型(内置类型,不可编辑) GVL_DB, // 共享内存模式 GVL_UNKNOWN // 无效的模式 }; /// /// 2022-2-15,各种变量分组类型在界面中显示的名称字符串 /// const static QStringList gvlTypeString = { "基础类型", "标准类型", "系统变量", "DB类型" }; /// /// Link连线的模式 /// enum class LINK_MODE : short { LINK_NORMAL, // 正常功能块的连线模式(横向五段线) LINK_PARALLEL // 并行连线的模式(纵向二段线) }; ///// ///// 2022-8-21,TOOL级别的接口定义,目前只有Start和End两种 ///// //enum class TOOL_INTERFACE : short //{ // INF_START, // INF_END, // TOOL_INTERFACE_COUNT // //}; ////======================================================== //// //// STRUCT //// ////======================================================== /// /// Pou、Tool的运行参数 /// typedef struct _tagExecutionParameters { int nExecTime; // 执行总时长(ms) int nExecCount; // 执行次数 int nErrorCount; // 错误次数 int nPreDelay; // 前延时(ms,仅Tool使用) int nPostDelay; // 后延时(ms) VPEnum::EXEC_STATUS nStatus; // 工具执行状态 VPEnum::RETURN_VALUE nRetValue; // 工具的执行返回值(默认为未执行状态) _tagExecutionParameters() { this->reset(); } void reset() { nExecTime = 0; nExecCount = 0; nErrorCount = 0; nPreDelay = 0; nPostDelay = 0; nRetValue = VPEnum::RETURN_VALUE::None; nStatus = VPEnum::EXEC_STATUS::StandBy; } // EXEC_PARAMS 序列化 friend QDataStream& operator<<(QDataStream& out, const _tagExecutionParameters& ep); // EXEC_PARAMS 反序列化 friend QDataStream& operator>>(QDataStream& in, _tagExecutionParameters& ep); } EXEC_PARAMS; /// /// Task 的运行参数 /// typedef struct _tagTaskParameters : public EXEC_PARAMS { bool bWatchDog; // 是否启用看门狗(仅Task使用) int nWatchDog; // 看门狗的设置数值(ms, 仅Task使用) VPEnum::PRIORITY nPriority; // 优先级 int nTriggerFailedCount; // 触发失败次数 TASK_RUN_MODE runMode; // 运行模式 _tagTaskParameters() { bWatchDog = true; nWatchDog = 200; nPriority = VPEnum::PRIORITY::NormalPriority; runMode = TASK_RUN_MODE::RUN_LOOP; nPostDelay = 200; nTriggerFailedCount = 0; } // TASK_PARAMS 序列化 friend QDataStream& operator<<(QDataStream& out, const _tagTaskParameters& tp); // TASK_PARAMS 反序列化 friend QDataStream& operator>>(QDataStream& in, _tagTaskParameters& tp); } TASK_PARAMS; //============================================================ // // Value // //============================================================ /// /// 接口的值信息 /// class VALUE { public: VALUE(); // 重载 = VALUE& operator =(const VALUE& v); // 重载 == bool operator==(const VALUE& other) const; // 是否是基础类型(目前只支持5种) bool isBaseType() const; // 是否是基础的数值类型(int float double) bool isBaseValueType() const; // 值是否是nullptr bool isNullptr() { return (this->Ptr == nullptr); } // 直接设置Ptr值的地址 void setValueByAddress(void** valuePtr) { this->Ptr = valuePtr; } // 根据传值或者传址设置不同的参数值 template void setValue(T v, VALUE_PASS_MODE mode = VALUE_PASS_MODE::PASS_BY_VALUE) { if (mode == VALUE_PASS_MODE::PASS_BY_VALUE) { if (this->Ptr == nullptr) { T* newValue = new T; *newValue = v; this->Ptr = (void**)newValue; } else { *(T*)this->Ptr = v; } } // 按地址为全局变量赋值(将全局变量指向到指定的内存地址,暂未使用) // TODO: 此处代码是错误的,不能使用 else if (mode == VALUE_PASS_MODE::PASS_BY_ADDRESS) { //if (this->value.Ptr == nullptr) //{ this->Ptr = (void**)&v; //} //else //{ // *this->value.Ptr = &v; //} } else { qWarning() << "[Value] [SetValue] Error: Invalid VALUE_PASS_MODE: " << (int)mode; } // this->value.strValueString = getValueByString(); //T* newValue = new T; //*newValue = v; //this->value.Ptr = newValue; } // 设置数值(按类型字符串) void setValue(const QString& strValue); // 获取数值 template T getValue() { return *((T*)this->Ptr); } // 2022-2-23 仅重置数值 void resetValue(); // 2022-3-25 清空Value void clear(); // 转换至 QString 类型 QString toString() const; // 转换至 int 类型 int toInt() const; // 转换至 float 类型 float toFloat() const; // 转换至 double 类型 double toDouble() const; // 转换至 bool 类型 bool toBool() const; // 序列化 friend QDataStream& operator<<(QDataStream& out, const VALUE& v); // 反序列化 friend QDataStream& operator>>(QDataStream& in, VALUE& v); public: VALUE_TYPE type; // 值类型 VALUE_PASS_MODE passMode; // 值的传递方式 void** Ptr; // 接口的值指针 // QString strValueString; // 字符串形式的数值 }; //============================================================ // // Interface // //============================================================ /// /// // 用于存储工具库中的工具接口静态信息 // (设计思路变更:让初始化加载的静态工具信息和加入POU执行的运行时工具信息分开) /// class STATIC_INTERFACE { public: STATIC_INTERFACE() { reset(); } void reset() { strName.clear(); Direction = INF_DIRECTION::INF_DIR_UNKNOWN; Discard = INF_DISCARD::INF_DEFAULT; Type = INF_TYPE::INF_TYPE_STANDARD; nIndex = -1; bEnable = true; bDynamic = false; bShowName = true; // eventTrigger = nullptr; value.clear(); } public: QString strName; // 接口名称 INF_TYPE Type; // 接口的类别 INF_DIRECTION Direction; // 接口的输入输出类型 INF_DISCARD Discard; // 该端口已经废弃的标志 // (备注:指在dll已经删除的端口,但是为了向下兼容,旧版本依然会加载。功能上会用黑色的端口显示) VALUE value; // 接口的值信息 // ToolEvent* eventTrigger; // 2022-9-19,为Event类型的接口保存触发事件 int nIndex; // 接口的序号 bool bEnable; // 是否启用此接口 bool bDynamic; // 是否是动态接口 bool bShowName; // 是否在界面中显示接口名称(Goto的输入接口,以及Start接口等,在界面中是不显示名称的) }; using DLL_INF = class STATIC_INTERFACE; /// /// 用于存储接口的运行时信息 // 2021-5-20调整,将TOOL和全局变量组整合到一起 // 每一个变量数据就相当于是一个接口 /// using GVL = class TOOL; class ToolEvent; class _INTERFACE : public STATIC_INTERFACE { public: // _INTERFACE(); _INTERFACE(TOOL* pParent, INF_TYPE type = INF_TYPE::INF_TYPE_STANDARD); // 根据用户的输入构造一个变量 // 2022-2-27,增加了DB变量需要的参数 _INTERFACE( const QString& strGroup, bool bSerialized, const QString& strName, const QString& strType, const QString& strValue, const QString& strComment, int nIndex, bool bShow, bool bTrigger = false, // 2022-9-1 增加,是否支持触发 const QString& strCommAddress = "", VPEnum::GVL_ACCESS_MODE mode = VPEnum::GVL_ACCESS_MODE::All ); // 从基础接口信息中扩展运行时信息 void basedFrom(const STATIC_INTERFACE& inf); //// 从Dll的接口中拷贝 //void copyFrom(const DLL_INF& dllInf); // 是否和指定的接口方向相同 bool isSameDirectionTo(const _INTERFACE* pInf) const; // 是否和指定的接口方向相反 bool isRevDirectionTo(const _INTERFACE* pInf) const; // 是否是相同类型 bool isSameTypeTo(const _INTERFACE* pInf, bool ignoreBaseType = false) const; // 2022-6-7,父工具是否是相同类型(用于检查Start接口之间的连接) bool isParentSameTypeTo(const _INTERFACE* pInf) const; // 是否是基础类型(目前只支持5种) bool isBaseType() const; // 是否是基础的数值类型(int float double) bool isBaseValueType() const; // 是否是输入接口(包括输入和双向两种) bool isDirInput() const; // 是否是输出接口(包括输出和双向两种) bool isDirOutput() const; // 本接口是否被Port绑定(Goto或者Port工具等等) bool isBinded() const; // 是否是Goto的ToolEnd接口 bool isGotoToolEnd() const; // 是否是Parallel的ToolStart接口 bool isParallelToolStart() const; // 是否是Parallel的ToolEnd接口 bool isParallelToolEnd() const; // 是否是ForLoop的ToolEnd接口 bool isForLoopToolEnd() const; // 是否是标准工具的ToolStart接口 bool isStandardToolStart() const; // 是否是Tool类型的输入接口 bool isToolStart() const; // 是否是Tool类型的输出接口 bool isToolEnd() const; // 是否是ToolInterface(Start、End) bool isToolInterface() const; //// 20210520增加,按照Variable的方式初始化本接口 //void setAsVariable(TOOL* pGroup, const QString& strGroup, const QString& strName); // 为接口中对应的dll数值赋值 template void setValue(T v, VALUE_PASS_MODE mode) { this->value.setValue(v, mode); //qDebug() << "[Interface][Value] Set " << this->strFullName // << " value to [" << Utility::getValueString(value.Ptr, value.Type) << "]."; // this->value.strValueString = getValueByString(); //T* newValue = new T; //*newValue = v; //this->value.Ptr = newValue; } // 为接口中对应的dll数值赋值 template bool setValue(T v) { // dll变量 if (this->value.Ptr == nullptr) { // 到dll中取值 T& currentValue = (*(T*)this->pParentTool->pDllPtr->Interface(this->nIndex).value.Ptr); if (currentValue != v) { // 如果不相等就写入数值 currentValue = v; return true; } } // 全局变量 else { T& currentValue = (*(T*)this->value.Ptr); if (currentValue != v) { // 如果不相等就写入数值 currentValue = v; return true; } } return false; } // 设置数值(按类型字符串,模板特化) void setValue(const QString& strValue); // 获取数值 template T getValue() { return this->value.getValue(); } // 获取Dll中的Value指针(因为exe本身不保存dll工具的值) void** getValuePtr() const; // 是否Value是空值 bool isValueNullptr() { return (this->value.Ptr == nullptr); } //// 2021-8-3增加,到dll中获取本接口的值(因为exe本身不保存dll工具的值) //void** getValuePtrFromDll(); // 设置数值对应的字符串 void setValueString(const QString& strValue); // 获取数值对应的字符串(For debug) QString getValueString() const; // 2022-3-23 获取真实的ParentTool(因为Port绑定的关系,接口的Parent需要转换一下) TOOL* realParent() const; // 获取本身的parent TOOL* parent() const; // 获取绑定接口的Parent(而非自身Parent) TOOL* bindedParent() const; // 设置Parent void setParent(TOOL* pParent); //// 序列化 //friend QDataStream& operator<<(QDataStream& out, const _INTERFACE& inf); //// 反序列化 //friend QDataStream& operator>>(QDataStream& in, _INTERFACE& inf); public: // TOOL* pOriginalTool; // 2021-6-13增加,接口原本的父工具(由于接口会被换绑到Port上,导致原本的父工具丢失) _INTERFACE* pUpLinkInterface; // 上联的Interface QVector<_INTERFACE*> pDownLinkInterfaces; // 下联的Interface(下联接口会有多个) _INTERFACE* pBindInterface; // 绑定的Interface(仅用于Port类型工具) QString strFullName; // 接口的全名(toolname.interfacename) QString strPropertyName; // 2022-1-18增加,变量在属性表中的属性名字(仅用于属性表) QString strNameWithType; // 2021-10-14增加,为了方便在界面中直接显示接口类型,加了一个以为结尾的名字 bool bWatch; // 是否启用变量监控,默认不启用,可在工具中配置默认状态 QString strComment; // 2021-5-20增加,接口的注释信息(仅变量) bool bSerialized; // 2021-5-20增加,是否进行值序列化(仅变量) bool bShow; // 2022-2-15增加,是否显示数值(仅变量) int nRefCount; // 引用计数(接口/变量) bool bDataLink; // 2021-11-9,是否与Runtime做了数据链接 QString valueString; // 2021-11-9,尝试性增加了本接口的数值字符串为了提高代码效率 // 由于接口本身不应该存储任何数值(存储在dll中),所以此处有待考证 bool bComplexLinkIndex; // 2021-12-14,是否被作为复杂控件的索引数值 // (备注:当索引数值变动时,需要向Runtime推送当前索引所有数据的变动通知) VPEnum::GVL_ACCESS_MODE accessMode; // 2022-2-26,变量存取权限(仅DB模式全局变量会用到) QString strCommAddress; // 2022-2-26,通信地址(仅DB模式全局变量会用到) ToolEvent* eventTrigger; // 2022-9-1,增加变量数值的变动通知(因为增加了变量变动触发Task的动作) protected: // 2022-3-23,防止此指针的错误使用,设置为私有 // 正确的用法应该是用 realParent() 获取真实的父工具(因为存在接口或者变量绑定到别的Tool中的情况) TOOL* pParentTool; // 从属的工具 }; // 增加一些同名名称 using VARIABLE = class _INTERFACE; using EVENT = class _INTERFACE; using VARIABLES = QVector<_INTERFACE*>; //============================================================ // // Tool // //============================================================ /////////////////////////////////////////////////////////// // 工具基础信息 class TOOL_BASE_INFO { public: TOOL_BASE_INFO(); TOOL_BASE_INFO( TOOL_TYPE type, QString name, QString aliasName, QString instanceName, QString category, QString version, QString info, QString comment = "" ); // 是否是Standard类型工具 bool isStandardTool() const; // 是否是Port类型的工具 bool isPortTool() const; // 是否是硬件类型的工具 bool isHardwareTool() const; // 是否是Goto类型的工具 bool isGotoTool() const; // 是否是Comment类型的工具 bool isCommentTool() const; // 是否是Parallel并行工具 bool isParallelTool() const; // 2022-8-21 是否是For循环工具 bool isForloopTool() const; // 2022-9-2 是否是Wait工具 bool isWaitTool() const; // 2022-8-21 是否是具备Tool接口的工具(例如标准工具、Parallel工具、For工具等等) bool isHaveToolInterfaces() const; // 2022-8-25 是否是具备索引序号的工具 bool isIndexedTool() const; // 2022-3-8 是否是默认值变量组 bool isDefaultValueGroup() const; //// 生成基础类型信息 //TOOL_BASE_INFO baseInfo() const; // 重载 = TOOL_BASE_INFO& operator =(const TOOL_BASE_INFO& v); public: TOOL_TYPE Type; // 工具的类型 QString strPouName; // 2021.7.4 增加,工具所属的Pou名字(Tool的分组,变量是所在的Gvl的名字) QString strName; // 工具名称 QString strAliasName; // 曾用名或者别名 QString strInstanceName; // 工具的实例名字 QString strCategory; // 工具所在的集合 QString strVersion; // 工具的版本 QString strInfo; // 工具的Info QString strComment; // 工具的注释信息 }; /////////////////////////////////////////////////////////// // 用于存储工具库中的工具的静态信息 class TOOL; class STATIC_TOOL : public TOOL_BASE_INFO { public: STATIC_TOOL() { Type = TOOL_TYPE::TOOL_TYPE_UNKNOWN; } // 2022-10-14,从TOOL中提取基础信息生成STATIC_TOOL(目前用于Undo体系中记录工具原始信息) STATIC_TOOL(const TOOL* tool); //// 2022-10-1,编写拷贝构造函数,完成工具原始信息的深度拷贝(目前用于Undo结构中) //STATIC_TOOL(const STATIC_TOOL& toolInfo); //// 2022-10-1,重载 = 运算符,完成工具原始信息的深度拷贝(目前用于Undo结构中) //STATIC_TOOL& operator = (const STATIC_TOOL& toolInfo); public: QString strDllPath; // 实现本工具的dll QVector staticInterfaces; // 接口的静态信息 }; using ToolActivator = QWaitCondition; /////////////////////////////////////////////////////////// // 用于存储Tool的运行时信息 class TOOL : public TOOL_BASE_INFO { public: // 为了GVL增加的构造函数(用于构造变量) TOOL(const QString& strName, TOOL_TYPE varType, GVL_MODE gvlMode); // 从工具箱中构造 TOOL(const STATIC_TOOL* pTool); // 构造一个空的工具(用于反序列化写入) TOOL(); //// 2022-10-1,编写拷贝构造函数,完成Tool的深度拷贝 //TOOL(const TOOL& tool); // 从指定的静态Tool信息中扩展 void basedFrom(const STATIC_TOOL* pTool); // 更新实例名字,并且通过实例名字更新接口的FullName void updateInstanceName(const QString& strInsName); // 根据名字获取指定接口 _INTERFACE* getInterfaceByName(const QString& strInfName); // 动态增加接口 void addInterface(_INTERFACE* newInf); // 根据名字动态删除接口 bool delInterfaceByName(const QString& strName); // 检查是否已经存在此接口了(按名称) bool contains(const QString& strName); // 2022-3-2 根据全名获取指定接口 _INTERFACE* getInterfaceByFullName(const QString& strInfFullName); // 2022-3-23 绑定一个Port接口(仅Port工具使用) void bindPortInterface(_INTERFACE* pSourceInf); // 获取本Port工具绑定的源接口(仅Port工具使用) _INTERFACE* bindedInterface(); // 本Port工具是否绑定了接口(仅Port工具使用) bool isBinded() const; // 重置本Port工具状态(仅Port工具使用) void resetPort(); // 设置本Port工具状态(仅Port工具使用) void setPortError(); // 获取ToolStart接口绑定的上级工具 TOOL* toolStartUpTool(); // 2022-8-28 本工具是否加入了并行组 bool isParallelSubTool(); // 2022-8-28 本工具是否加入了For循环 bool isForloopSubTool(); int GetInterfaceSize(); // 排序(用于在Pou中保持执行队列按index有序) static bool sort_by_index(const TOOL* t1, const TOOL* t2) { return t1->nIndex < t2->nIndex; } // 2022-9-5 工具等待触发执行 VPEnum::RETURN_VALUE waitForExecution(unsigned long timeOut = ULONG_MAX); public: DllTool* pDllPtr; // 工具Dll运行的实例指针 TOOL* parentTool; // 2022-4-18,本工具所属的工具组(目前只有并行工具组) QVector<_INTERFACE*> Interfaces; // Tool的标准接口 //_INTERFACE* startInterface; // 2022-4-5增加,Tool级别的输入接口,2022-8-21,从Top重命名为Start // //(用于执行Goto跳转,及其他Tool直连的链接,仅标准工具使用) //_INTERFACE* endInterface; // 2022-8-21 增加,Tool界别的输出接口,用于执行与下级的Tool直接连接 QVector<_INTERFACE*> ToolInterfaces; // 2022-8-21 改动,将Tool接口定义为了数组,方便扩展 // 目前总共有两个Tool级别接口 #define INF_START 0 #define INF_END 1 #define TOOL_INTERFACE_COUNT 2 #define startInterface ToolInterfaces[INF_START] #define endInterface ToolInterfaces[INF_END] // _INTERFACE* pBindInterface; // Port绑定的源接口的指针(仅Port类型) #define Variables Interfaces // (仅变量类型使用) // 工具执行的相关参数 bool bEnable; // 是否启用本工具 int nIndex; // 工具的执行序号 bool bEnableBreakPoint; // 启用断点 EXEC_PARAMS execParams; // 执行参数 GVL_MODE gvlMode; // 全局变量的模式(仅用于变量) // DllTool* pHdwDllPtr; // 2022-3-2,本DB数据绑定的硬件工具(仅用于DB模式变量) QString strHdwInstName; // 本DB数据绑定的硬件工具实例名称(仅用于DB模式变量) // bool bParallelized; // 2022-5-4,是否加入了并行组(2022-8-28去掉,改为运行时实时判定) // ToolEvent* eventTrigger; // 2022-9-3,Tool也加入了Event触发机制(用于给Wait工具使用) QMutex mutex; // Tool与Event对应的互斥量,用于等待事件触发 ToolActivator activator; // 2022-9-3,TaskManager中用于触发Tool的事件(目前用于Wait工具) }; // 变量组 using GVLS = QMap; /////////////////////////////////////////////////////////// // class PORT : public TOOL_BASE_INFO { public: PORT(const STATIC_TOOL* pTool); // 从指定的静态Tool信息中扩展 void basedFrom(const STATIC_TOOL* pTool); public: QVector<_INTERFACE*> Interfaces; // 自带的接口(理论上Port有且仅有一个接口,输入/输出) _INTERFACE* pBindInterface; // Port绑定的源接口的指针 }; /// /// 用于存储工具库中的工具类别 /// class TOOL_CATEGORY { public: TOOL_CATEGORY() { } public: QString strName; // 分类的名称 QVector staticTools; // 本分类下的所有工具的静态信息 }; //============================================================ // // Task、Event // //============================================================ /// /// ToolEvent中的执行方式 /// enum class TOOL_EVENT_TYPE : short { TOOL_TRIGGER, // 触发执行某个工具 TASK_TRIGGER, // 触发执行Task //TOOL_TRIGGER_BY_VALUE, // 按照等于某个值时触发工具 //TASK_TRIGGER_BY_VALUE // 按照等于某个值时触发Task(暂未实现) }; /// /// 工具中的事件接口类型 /// class ToolEvent : public QEvent { public: ToolEvent() : // QEvent((QEvent::Type)QEvent::registerEventType(QEvent::User + genRandNumber(0, 60000))); // 此处似乎不需要随机生成ID,系统会从MaxUser开始自动往下分配 QEvent((QEvent::Type)QEvent::registerEventType()) { m_exType = TOOL_EVENT_TYPE::TASK_TRIGGER; } // QEvent((QEvent::Type)QEvent::registerEventType(QEvent::User + genRandNumber(0, 60000))); // 此处似乎不需要随机生成ID,系统会从MaxUser开始自动往下分配 // 这个ID号是 ToolEvent(const QString& strGroupName, const QString& strName, TOOL_EVENT_TYPE type) : QEvent((QEvent::Type)QEvent::registerEventType()) { setName(strGroupName, strName); m_exType = type; } ~ToolEvent() {}; // 设定Event的名字(Tool.Interface的全名以及GroupName) void setName(const QString& strGroupName, const QString& strName) { this->m_strGroupName = strGroupName; this->m_strEventName = strName; } // 设定Event的GroupName(默认都是 HARDWARE_GROUP_NAME,以防万一需要扩展,还是保存一下 ) // 获取Event的名字 QString name() const { return m_strEventName; } // 获取GroupName QString groupName() const { return m_strGroupName; } void setExType(TOOL_EVENT_TYPE type) { m_exType = type; } TOOL_EVENT_TYPE getExType() const { return m_exType; } // 2022-9-25 为了实现等于某个值的事件触发增加 VALUE m_triggerValue; protected: QString m_strEventName; QString m_strGroupName; TOOL_EVENT_TYPE m_exType = TOOL_EVENT_TYPE::TASK_TRIGGER; public: // 事件携带的返回值 VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::Success; }; // 设置别名 using TaskActivator = QWaitCondition; using EVENT_ID = QEvent::Type; /// /// 用于UI、Runtime和Dll同步的消息 /// enum class UI_SYNC_MSG : short { EDIT_TEXT_CHANGED, COMBO_SEL_CHANGED, LIST_SEL_CHANGED, CHECKBOX_CHANGED, RADIOBOX_CHANGED, VALUE_CHANGED, UNKNOWN_MSG }; /// /// 控件到Runtime的同步事件(每次仅一个控件同步) /// #define CONTROL_EVENT_TYPEID QEvent::Type::User + 10 class SyncControlEvent : public QEvent { public: SyncControlEvent() : QEvent(eventType()) { } ~SyncControlEvent() {}; static Type eventType() { // 创建事件Type if (m_EventType == QEvent::None) { m_EventType = (QEvent::Type)QEvent::registerEventType(CONTROL_EVENT_TYPEID); } return m_EventType; } // 待同步的控件句柄 QWidget* m_pSrcControl = nullptr; // 待同步的控件事件类型 UI_SYNC_MSG m_SyncMsg = UI_SYNC_MSG::UNKNOWN_MSG; private: static Type m_EventType; }; /// /// 数值到Runtime的同步事件(WindowRuntime用) /// 同时也作为动态接口到Pou的同步事件(UiManager用) /// 同时也作为全局变量在表格中的变动通知(GvlManager用) /// #define VALUE_EVENT_TYPEID QEvent::Type::User + 11 class SyncValueEvent : public QEvent { public: SyncValueEvent() : QEvent(eventType()) { } ~SyncValueEvent() {}; static Type eventType() { // 创建事件Type if (m_EventType == QEvent::None) { m_EventType = (QEvent::Type)QEvent::registerEventType(VALUE_EVENT_TYPEID); } return m_EventType; } // 待同步数据项 void addSyncValue(VARIABLE* val) { m_SyncValues.push_back(val); } QList getSyncValues() const { return m_SyncValues; } void setSyncValues(const QList& listInf) { m_SyncValues = listInf; } private: static Type m_EventType; // Value(一个或多个) QList m_SyncValues; }; /// /// 硬件数值接口到Runtime的同步事件 /// #define HDVALUE_EVENT_TYPEID QEvent::Type::User + 12 class SyncHdValueEvent : public QEvent { public: SyncHdValueEvent() : QEvent(eventType()) { } ~SyncHdValueEvent() {}; // 设定Event的 GroupName void setGroupName(const QString& strGroupName) { this->m_strGroupName = strGroupName; } // 获取GroupName QString groupName() const { return m_strGroupName; } static Type eventType() { // 创建事件Type if (m_EventType == QEvent::None) { m_EventType = (QEvent::Type)QEvent::registerEventType(HDVALUE_EVENT_TYPEID); } return m_EventType; } // 需要同步的硬件接口信息 // 第一种同步方式,按实例名和接口名同步 QString m_strInstanceName; // 实例名称 QString m_strInfName; // 接口名称 // 第二种同步方式:直接按数值指针同步 void* m_pSrcValue = nullptr; // 接口数值指针 protected: QString m_strGroupName; private: static Type m_EventType; }; /// /// 动态接口到Pou的同步事件 /// #define DLLINF_EVENT_TYPEID QEvent::Type::User + 13 class SyncInterfaceEvent : public QEvent { public: SyncInterfaceEvent() : QEvent(eventType()) { } ~SyncInterfaceEvent() {}; static Type eventType() { // 创建事件Type if (m_EventType == QEvent::None) { m_EventType = (QEvent::Type)QEvent::registerEventType(DLLINF_EVENT_TYPEID); } return m_EventType; } // 待同步动态接口 void addSyncInterface(const DLL_INF val) { m_SyncDllInfs.push_back(val); } QList getSyncInterfaces() const { return m_SyncDllInfs; } void setSyncValues(const QList listInf) { m_SyncDllInfs = listInf; } // 待同步接口的工具实例名称 QString m_strInstanceName; // true 是增加, false 是删除 bool m_bAdd = true; // 执行结果 bool m_bSuccess = false; // 原因(如果出错) QString m_strReason; private: static Type m_EventType; // Interface(一个或多个) QList m_SyncDllInfs; }; typedef struct _tagDisplay { public: HObject ho_Obj; QColor Color; double fTransparency; int nLinsWhite; public: _tagDisplay() { nLinsWhite = 0; fTransparency = 0; } _tagDisplay(HObject obj, QColor color = qRgb(255, 0, 0), double fTransparency = 0.0, int nLinsWhite = 1) { this->ho_Obj = obj; this->Color = color; this->fTransparency = fTransparency; this->nLinsWhite = nLinsWhite; } void setObject(HObject obj, QColor color = qRgb(255, 0, 0), double fTransparency = 0.0, int nLinsWhite = 1) { this->ho_Obj = obj; this->Color = color; this->fTransparency = fTransparency; this->nLinsWhite = nLinsWhite; } void Clear() { this->ho_Obj.Clear(); this->Color = qRgb(255, 0, 0); this->fTransparency = 0.0; this->nLinsWhite = 1; } _tagDisplay& operator =(const _tagDisplay& disp) { if (this != &disp) { this->ho_Obj = disp.ho_Obj; this->Color = disp.Color; this->fTransparency = disp.fTransparency; this->nLinsWhite = disp.nLinsWhite; } return *this; } } ST_Display; typedef struct _tagMessage { public: HTuple hv_Msg; int nX; int nY; int nMsgSize; QColor Color; public: _tagMessage() { Clear(); } _tagMessage(HTuple hvMsg, QColor color = qRgb(255, 0, 0), int nX = 10, int nY = 10, int nMsgSize = 10) { this->hv_Msg = hvMsg; this->Color = color; this->nX = nX; this->nY = nY; this->nMsgSize = nMsgSize; } void setMsg(HTuple hvMsg, QColor color = qRgb(255, 0, 0), int nX = 10, int nY = 10, int nMsgSize = 10) { this->hv_Msg = hvMsg; this->Color = color; this->nX = nX; this->nY = nY; this->nMsgSize = nMsgSize; } void Clear() { hv_Msg.Clear(); this->Color = qRgb(255, 0, 0); this->nX = 10; this->nY = 10; this->nMsgSize = 10; } _tagMessage& operator =(const _tagMessage& msg) { if (this != &msg) { this->hv_Msg = msg.hv_Msg; this->Color = msg.Color; this->nX = msg.nX; this->nY = msg.nY; this->nMsgSize = msg.nMsgSize; } return *this; } }ST_Message; typedef struct _tagDebugLog { public: QString strName; QString strLog; public: _tagDebugLog() { Clear(); } _tagDebugLog(QString strName, QString strLog) { this->strName = strName; this->strLog = strLog; } void Clear() { this->strName = ""; this->strLog = ""; } _tagDebugLog& operator =(const _tagDebugLog& log) { if (this != &log) { this->strName = log.strName; this->strLog = log.strLog; } return *this; } }ST_DebugLog; /// /// 用于Debug输出的结构体 /// typedef struct _tagDebugData { public: _tagDebugData() { Clear(); } void Clear() { listDisplay.clear(); listMessage.clear(); listDebugLog.clear(); } void addImage(HImage img) { ho_Image = img; } void addObj(HObject obj, QColor color = qRgb(255, 0, 0), double fTransparency = 0.0, int nLinsWhite = 1) { ST_Display disp(obj, color, fTransparency, nLinsWhite); listDisplay.push_back(disp); } void addMsg(HTuple hvMsg, QColor color = qRgb(255, 0, 0), int nX = 10, int nY = 10, int nMsgSize = 10) { ST_Message msg(hvMsg, color, nX, nY, nMsgSize); listMessage.push_back(msg); } void addLog(QString strName = "NULL", QString strLog = "Log") { ST_DebugLog debuglog(strName, strLog); listDebugLog.push_back(debuglog); } _tagDebugData& operator =(const _tagDebugData& data) { if (this != &data) { this->ho_Image = data.ho_Image; this->listDisplay = data.listDisplay; this->listMessage = data.listMessage; this->listDebugLog = data.listDebugLog; } return *this; } HImage getImage() { return ho_Image; } ST_Display getDisplay(int index) { ST_Display disp; if ((index >= 0) && (index < listDisplay.size())) { disp = listDisplay[index]; } return disp; } ST_Message getMessage(int index) { ST_Message msg; if ((index >= 0) && (index < listMessage.size())) { msg = listMessage[index]; } return msg; } ST_DebugLog getDebugLog(int index) { ST_DebugLog log; if ((index >= 0) && (index < listDebugLog.size())) { log = listDebugLog[index]; } return log; } int getDisplaySize() { return listDisplay.size(); } int getMessageSize() { return listMessage.size(); } int getDebugLogSize() { return listDebugLog.size(); } protected: HImage ho_Image; QList listDisplay; QList listMessage; QList listDebugLog; } DebugData; /// /// 存储图片和窗口转储的数据结构 /// typedef struct _tagSaveImg { HImage hoImage; HImage hoDumpWindow; QString strFileName; QString strFilePath; HTuple hvWindow; // 0 == NULL , 1 == OK, 2 == NG int nExecuteState; bool bEnSaveImage; bool bEnSaveDumpWindow; bool bEnExecuteState; int nSaveMode; int nBufferSize; int nFreeTime; _tagSaveImg() { hoImage.Clear(); hoDumpWindow.Clear(); strFileName = ""; strFilePath = ""; nExecuteState = 0; bEnSaveImage = false; bEnSaveDumpWindow = false; nSaveMode = 0; nBufferSize = 100; nFreeTime = 100; } }SAVE_IMG; typedef struct _tagST_Pos { HTuple hv_Row; HTuple hv_Column; HTuple hv_Angle; HTuple hv_HomMat2D; _tagST_Pos() { Clear(); } void Clear() { hv_Row.Clear(); hv_Column.Clear(); hv_Angle.Clear(); hv_HomMat2D.Clear(); } } ST_POS;