This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,511 @@
# DataOperator
<cite>
**本文档引用的文件**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DataOperator.h](file://h/DataOperator.h)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TaskDataOper.h](file://h/TaskDataOper.h)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [TdManager.h](file://h/TdManager.h)
- [TestingData.h](file://h/TestingData.h)
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
DataOperator模块是GeomativeStudio软件中负责数据读写、处理与管理的核心组件。该模块主要负责与TdManager协同工作,实现测试数据的加载、保存和格式转换,支持Excel、CSV、TXT、URF等多种导出格式。通过TaskDataOper类,实现了任务数据的操作流程,包括数据序列化、反序列化及内存管理策略。DataOperator模块在实际业务场景中,如从设备读取原始测量数据并持久化到项目文件中的完整流程,展现了其强大的数据处理能力。此外,该模块还深入分析了与ADO数据库交互的实现机制,包括记录集操作和异常处理,确保了数据操作的稳定性和可靠性。
## 项目结构
GeomativeStudio项目结构清晰,主要分为CACHE、DB、Install、LOG、Release、cpp、h、res、tools等目录。其中,cpp目录下的Operator子目录包含了DataOperator和TaskDataOper等核心操作类的实现文件,Managers目录下的TdManager.cpp文件则负责测试数据的管理。h目录下的头文件定义了各个类的接口和数据结构,为模块间的协同工作提供了基础。整个项目结构体现了模块化设计的思想,便于维护和扩展。
```mermaid
graph TD
subgraph "核心模块"
DataOperator[DataOperator.cpp]
TaskDataOper[TaskDataOper.cpp]
TdManager[TdManager.cpp]
end
subgraph "工具类"
Excel[excel.cpp]
OperTxtFile[OperTxtFile.cpp]
OperUrfFile[OperUrfFile.cpp]
end
subgraph "头文件"
DataOperatorH[DataOperator.h]
TaskDataOperH[TaskDataOper.h]
TdManagerH[TdManager.h]
TestingDataH[TestingData.h]
end
DataOperator --> TdManager
DataOperator --> TaskDataOper
TaskDataOper --> TdManager
DataOperator --> Excel
DataOperator --> OperTxtFile
DataOperator --> OperUrfFile
DataOperatorH --> DataOperator
TaskDataOperH --> TaskDataOper
TdManagerH --> TdManager
TestingDataH --> TdManager
```
**图源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 核心组件
DataOperator模块的核心组件包括DataOperator类、TaskDataOper类和TdManager类。DataOperator类负责数据的读写和管理,通过与TdManager类的协同工作,实现了测试数据的加载、保存和格式转换。TaskDataOper类则专注于任务数据的操作流程,包括数据的序列化、反序列化及内存管理策略。这些核心组件共同构成了DataOperator模块的基础,确保了数据处理的高效性和可靠性。
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 架构概述
DataOperator模块的架构设计充分考虑了模块化和可扩展性。通过定义清晰的接口和数据结构,实现了各组件间的松耦合。DataOperator类作为数据操作的入口,通过调用TaskDataOper类和TdManager类的方法,完成具体的数据处理任务。这种设计不仅提高了代码的可读性和可维护性,还便于后续的功能扩展和性能优化。
```mermaid
classDiagram
class DataOperator {
+_ConnectionPtr m_pConnection
+CStateProcessor m_stateProcessor
+CHandleProcessor m_handleProcessor
+InitialNavDataView(CNavDataView* pNavDataView)
+ShowProjectInfo(DWORD dwProHandle, CView *pAppDataView)
+ShowTzInfo(DWORD dwTzHandle, CView *pAppDataView)
+ShowRsp3DTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+ShowRsp2DTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+ShowRspCETdInfo(DWORD dwTdHandle, CView* pAppDataView)
+LoadRspCERecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+LoadRsp2dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+LoadRsp3dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+ShowIps2DpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+ShowIps3DpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+ShowIpsCEpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+LoadIpspCERecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+LoadIpsp2dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+LoadIpsp3dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+CreateProjectInDB(CNavDataView* pNavDataView)
+DeleteProjectInDB(CNavDataView* pNavDataView)
+DeleteTzInDB(CNavDataView* pNavDataView)
+Convert2DTo3D(CNavDataView* pNavDataView)
+Delete3DRecord(CNavDataView *pNavDataView, int iTSN)
+Delete1DRecord(CNavDataView *pNavDataView, int iTSN)
+Delete2DRecord(CNavDataView *pNavDataView, int iTSN)
+DeleteSPCETdInDB(DWORD dwTdID)
+DeleteSP2DTdInDB(DWORD dwTdID)
+DeleteSP3DTdInDB(DWORD dwTdID)
+DeleteRspCETdInDB(DWORD dwTdID)
+DeleteRsp2DTdInDB(DWORD dwTdID)
+DeleteRsp3DTdInDB(DWORD dwTdID)
+DeleteIpspCETdInDB(DWORD dwTdID)
+DeleteIpsp2DTdInDB(DWORD dwTdID)
+DeleteIpsp3DTdInDB(DWORD dwTdID)
+DisplayRsp2DTdGraph(CNavDataView *pNavDataView)
+DisplayRsp3DTdGraph(CNavDataView *pNavDataView)
+DisplayRspCETdGraph(CNavDataView *pNavDataView)
+DisplayTPSplinesGraph(CNavDataView *pNavDataView, int iTSN)
+ExportIpCETdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIp2DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIp3DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIpCETdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIp2DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIp3DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIpSpCETdToDAT(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIP2DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIP3DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportIP1DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSPCETdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP2DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP3DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSPCETdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP2DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP3DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSPCETdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP2DTdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportSP3DTdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp1DTdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp2DTdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp3DTdToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRspCETdToDAT(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp2DTdToDAT(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp3DTdToDAT(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRspCETdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp2DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp3DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRspCETdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp2DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp3DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp2DTdToUrf(CNavDataView *pNavDataView, CString f_szFileName)
+ExportRsp3DTdToUrf(CNavDataView *pNavDataView, CString f_szFileName)
+Delete1DElectrodeRecord(CNavDataView *pNavDataView, const std : : vector<float>* pvtDelElecID)
+Delete2DElectrodeRecord(CNavDataView *pNavDataView, const std : : vector<float>* pvtDelElecID)
+Delete3DElectrodeRecord(CNavDataView *pNavDataView, const std : : vector<float>* pvtDelElecID)
+ExportTdRecFile(CNavDataView *pNavData)
+ExportTdOrgFile(CNavDataView *pNavData)
+SaveRecFileToLocal(CString strRecFile, CString strDstFile,int iTaskType)
+QueryTaskARInDB(DWORD dwTdHandle)
}
class TaskDataOper {
+_RecordsetPtr m_pRecTdData
+bool m_bIsOpenTdData
+BYTE m_iTdType
+int m_iTestType
+WORD m_wMaxChannel
+time_t m_tStartTime
+time_t m_tEndTime
+CGUCodeCreator m_guCodeCreator
+GetDefaultTzID()
+Create1DTask(const ST1DTaskParam& stTaskParam,CString strTaskCN)
+Create2DTask(const ST2DTaskParam& stTaskParam, CString strTaskCN)
+Create3DTask(const ST3DTaskParam& stTaskParam, CString strTaskCN)
+QuerySptByAR(int iAR, std : : vector<STQuerySptInfo>& vtQuerySptRes, int iSptType)
+QuerySptRectByARandSCname(int iAR, CString strSCname, CString& vtQuerySptRes, CString& strPoleStep, CString& strPoleDistance, CString& strLineDirection, BYTE& ucSptType)
+QueryMediumInfo(int iSptType, std : : vector<STQueryMediumInfo>& vtQueryAR)
+QueryCmInfo(CString strCName, std : : vector<STQueryCMInfo>& vtQueryCM)
+DeleteTask(int iTaskID)
+DeleteTaskArray(std : : vector<int> vtTaskID)
+DeleteTaskArray(std : : vector<CString> vtTaskID)
+Query2DSptInfo(int iSptID, int &iMinLayer,int &iMaxLayer)
+QuerySptElecTpMount(int iSptID, int &iEAmount, int &iTpMount)
+QueryTdBasicInfo(int iTaskID, STQueryTaskBasicInfo* pTaskBasicInfo,CString strTaskCN=_T(""))
+UpdateGrData(int iTaskID, const char* pData,int iSptType,int iAddedVal = 0)
+InsertGrData(int iTaskID, WORD wGrNum, const char* pData, int iSptType=1)
+InsertCoordinatesData(CString strTaskID, WORD wGrNum, const char* pData,float fMaxWellDepth, int iSptType = 1)
+DeleteGrInfo(int iTaskID, WORD wElecID, BYTE ucDelFlag)
+DeleteTdDataInfo(BYTE ucTdType, int iTaskID, WORD wTSN, BYTE ucDelFlag)
+OpenTdData(int iTaskID, BYTE ucTdType, WORD wStartTSN = 0, WORD wMaxChannel = 1)
+CloseTdData()
+QueryNextTdBasicData(std : : vector<STSigSndDataInfo>& vtTestData)
+QueryTdSigBasicData(int iTaskID, BYTE ucTdType, WORD wTSN, LPSTSigSndDataInfo pMeasuBasicReq)
+UpdateTdBasicData(BYTE ucTdType, BYTE ucTestType,int iTdChannelID, int iTsn, LPSTMeasuBasicDataRes pMeasuBasicData,void *pAttachData)
+UpdateTdBasicData(BYTE ucTdType, BYTE ucTestType, int iTdChannelID, int iTsn, LPSTMeasuBasicDataResEx pMeasuBasicData, void *pAttachData)
+OnlineDownloadRes2DData(BYTE ucTdType, STTaskDataRes *ptTaskData, DWORD dwChID)
+OnlineUploadRes2DTask(DWORD dwChID)
+OnlineUploadRes2DArg(DWORD dwChID, STQueryTaskBasicInfo stQueryTdInfo)
+OnlineUploadRes2DRg(DWORD dwChID, STQueryTaskBasicInfo stQueryTdInfo)
+OnlineUploadRes2DData(DWORD dwChID, STQueryTaskBasicInfo stQueryTdInfo)
+UploadElecCoordinatesInfo(DWORD dwTdID, STQueryTaskBasicInfo stQueryTdInfo)
+QueryTdDataFromTsn(int iTaskID, BYTE ucTdType, WORD wStartTSN, int iCnt, std : : vector<STTaskDetailBasicData>& vtRes)
+QueryTdDataByElec(int iSptID, BYTE ucTdType, int iStartElec, int iEndElec, std : : vector<STTaskDetailBasicData>& vtRes)
+QueryElecMaxWellDepthByCN(CString strScriptCN, BYTE ucTdType, STElecCoordinatesInfoHead& stElecInfoHead)
+QueryElecCoordinatesDataByCN(CString strScriptCN, BYTE ucTdType, WORD wStartTSN, int iCnt, std : : vector<STElecCoordinatesInfoBody>& vtRes)
+QueryTdAttrToCtrl(CListCtrl& listAttr, int iTaskID)
+QueryTdDataToCtrl(CListCtrl& listData, int iTaskID, int iSptType, int iTestType)
+QueryOnLineTdAttrToCtrl(CListCtrl& listAttr, STTaskListItem taskItem, STRemTaskArg *pstTaskArg)
+QueryOnLineTdAttrFromSev(STRemTaskTable stTaskTable, STRemTaskArg *pstTaskArg)
+QueryOnLineTdRgFromSev(STRemTaskArg stTaskArg, char *pRg)
+QueryOnLineElecInfoFromSev(STRemTaskArg stTaskArg, char* pElecInfo)
+QueryOnLineTdDataFromSev(STRemTaskArg stTaskArg, UINT32 uiStartPoint, UINT32 uiEndPoint, char *pData)
+QueryOnLineTdDataToCtrl(STRemTaskArg stTaskArg, std : : vector<STTaskDetailBasicData>& vtData)
+InitialTaskTreeCtrl(CTreeCtrl& taskTree,int iSptType)
+InitOnLineTaskTreeCtrl(CTreeCtrl& taskTree, int iSptType, std : : map<CString, STRemTaskTable> mapTaskList, HWND hWnd)
+QueryTimerTaskValiad(std : : vector<STTimerTask>& vtTimerTask, const SYSTEMTIME &sysCurTime)
+DeleteTimerTask(const std : : vector<int>& vtTask)
+DeleteTimerTask(UINT32 uiTDID)
+QueryTdBrowseInfo(std : : vector<STTdBrowseInfo>& vtTdBrowseInfo, bool bIsQueryTimerTd=false)
+QueryTdBrowseInfo(std : : vector<STTdBrowseInfo>& vtTdBrowseInfo, int iSptType, int iType ,bool bIsQueryTimerTd=false)
+AddTimerTask(int iTaskID, CString strTaskName, CString strTime,CString strPlcID)
+InsertPlcStatusData(const STRemPlcDataInfo* pRemPlcData)
+QueryPlcStatusData(std : : vector<STPlcStatusInfo>& vtPlcStatus)
+DeleteOldPlcStatusData()
+QueryTaskPacketAttr(int& iLoopTime, int& iInterval, CString& strPlcID)
+QueryTaskPacketInfo(std : : vector<STTdBrowseInfo>& vtTdBrowseInfo)
+InsertTaskPacketInfo(const std : : vector<STTdBrowseInfo>& vtTdBrowseInfo, const STTaskPacketAttr& stAttr)
+CreateSigTaskByAuto(const STTdBrowseInfo& stBasicTask, CString strTime, STTdBrowseInfo& stNewTask)
+CreateTaskPacket(const std : : vector<STTdBrowseInfo>& vtBasicTaskPacket, CString strSysTime, std : : vector<STTdBrowseInfo>& vtNewTaskPacket)
+QueryARByTdID(DWORD dwTdID)
+AdjustParam()
+SetCurrentTimeRange(time_t tStartTime, time_t tEndTime)
+unsigned int m_uiDevID
}
class TdManager {
+CLinkList<CTestingData*> m_tdLinkList
+_ConnectionPtr m_pConnection
+FILE *m_pFile
+CString m_log
+DeleteSPCETd(DWORD dwID)
+DeleteSP3DTd(DWORD dwID)
+DeleteSP2DTd(DWORD dwID)
+DeleteRsp3DTd(DWORD dwID)
+DeleteIpsp3DTd(DWORD dwID)
+CheckTdExist(CString szPrCN, CString szTzCN, CString szTdCN, CDevice* const pDev,DWORD *TdId)
+OnlineCheckTdExist(CString szTdID, CString szDevSN, DWORD *TdId)
+OnlineCheckElecInfoExist(CString strTdID, CString szDevSN)
+ImportTdHeadToDB(DWORD dwTzID, CString szHeadFile, CDevice* const pDev,DWORD* pExTdID = NULL)
+Import2DTdOrgToDB(DWORD dwTdID, CString szOrgFile, CDevice* const pDev)
+ImportCETdOrgToDB(DWORD dwTdID, CString szOrgFile, CDevice* const pDev)
+Import3DTdOrgToDB(DWORD dwTdID, CString szOrgFile, CDevice* const pDev)
+Import2DTdConToDB(DWORD dwTdID, CString szDatFile, CDevice* const pDev, int* pTSN=NULL)
+ImportCETdConToDB(DWORD dwTdID, CString szDatFile, CDevice* const pDev)
+Import3DTdConToDB(DWORD dwTdID, CString szDatFile, CDevice* const pDev, int* pTSN = NULL)
+Import2DGRToDB(DWORD dwTdID, CString szGRFile, CDevice* const pDev)
+Import3DGRToDB(DWORD dwTdID, CString szGRFile)
+ImportCETGRToDB(DWORD dwTdID, CString szGRFile)
+UploadCETdFromDev(CString szPrCN, CString szTzCN, CString szTdCN, CString strSubTdCN, CDevice* const pDev)
+Upload2DTdFromDev(CString szPrCN, CString szTzCN, CString szTdCN, CString strSubTdCN, CDevice* const pDev)
+Upload3DTdFromDev(CString szPrCN, CString szTzCN, CString szTdCN, CString strSubTdCN, CDevice* const pDev)
+UploadWellTdFromDev(CString szPrCN, CString szTzCN, CString szTdCN, CString strSubTdCN, CDevice* const pDev)
+DeleteTdInDev(CString szPrCN, CString szTzCN, CString szTdCN, CDevice* const pDev)
+InitialTDListByTzForSyn(CListCtrl &tdList, CString szDeSN, CString szTzCN)
+InitialTDListByProForSyn(CListCtrl &tdList, CString szDeSN, CString szPrCN)
+InitialTDListByOnLineForSyn(CListCtrl &tdList, CString szDeSN, UINT32 &uiTotNum)
+InitialDevListByOnLineForSyn(CListCtrl &tdList, CString szDeSN,STSynDevParam *ptLocalDevParam)
+InitialCableListByOnLineForSyn(CListCtrl &tdList, CString szDeSN, STRemCableCallInfo *ptLocalCableInfo)
+OnlineSevTDListSynToDB(STRemTaskArg *tTaskArg, CString szDeSN)
+OnLineImportTdHeadToDB(STRemTaskArg *tTaskArg, CString szDevSN)
+Convert2DTo3D(DWORD dwTzHandle)
+DeleteObjInMem(DWORD dwHandle)
+DeleteRspCETd(DWORD dwID)
+DeleteIpspCETd(DWORD dwID)
+DeleteRsp2DTd(DWORD dwID)
+DeleteIpsp2DTd(DWORD dwID)
+GetTestingData(DWORD dwHandle)
+ShowTdListByTz(DWORD dwTzHandle, CListCtrl& tdList)
+ShowTd2DListByTz(DWORD dwTzHandle, int iEAmount, float fEDistance, int iAR, CListCtrl& tdList)
+ShowTdListByDev(DWORD dwDevHandle, CListCtrl& tdList)
+ImportTdSpecAttr(const CStringArray& strAttrArray, int iDataType, DWORD dwChID,int iTSN)
+ShowTdListByProject(DWORD dwProHandle, CListCtrl& tdList)
+GetTaskAttr(DWORD dwHandle, DWORD& dwTdID, int& iStyle)
}
class CTestingData {
+CDevice* m_pDevice
+DWORD m_dwID
+CString m_szTdName
+CString m_szTdCN
+CString m_szTLocation
+CString m_szPrCN
+CString m_szTzName
+CString m_szTzCN
+DWORD m_dwTzID
+DWORD m_dwSCID
+CString m_szSCCN
+CString m_szSName
+int m_iSType
+int m_iTType
+int m_iTMode
+int m_iEAmount
+int m_iTPAmount
+int m_iCHAmount
+int m_iN
+int m_iTRWave
+int m_iTRFrequency
+int m_iIFrequency
+int m_iSAFrequency
+int m_iCLayout
+float m_fEspace
+float m_fEdistance
+CString m_strRect
+CString m_strValidElec
+CString m_strValildLayer
+int m_iStartElec
+int m_iEndElec
+int m_iStartLayer
+int m_iEndLayer
+int m_iRollCnt
+int m_iSkipCable
+int m_iAR
+int m_iTxWave
+int m_iTxPeriod
+int m_iSAInterval
+int m_iWeather
+int m_iWDIR
+float m_fTemperature
+float m_fHeight
+float m_fHumidity
+CString m_strCdate
+CString m_strCtime
+CString m_strTdate
+CString m_strTtime
+int m_iRdirection
+int m_iCRtime
+CString m_strPM
+CString m_strOP
+CString m_strQA
+int m_iTestGRFlag
+int m_iLineDirection
+int m_iCreateTime
+int m_iSTime
+int m_iETime
+int m_iTTimer
+int m_iTdStatus
+int m_iDesn
+int m_iStacking
+int m_iTestPeriod
+int m_iCableLayout
+int m_iSAInterval
+int m_iEamount
+int m_iTestPeriod
+int m_iCableLayout
+int m_iStartElec
+int m_iEndElec
+int m_iStacking
+int m_iTxWave
+int m_iTxPeriod
+int m_iSAInterval
+int m_iEAmount
+float m_fEspace
+float m_fHoleSpace
+unsigned int m_uiDevID
+unsigned int m_uiTimerTime
+BYTE m_ucOrgFlg
+BYTE m_ucTestGRFlag
+UpdataTopography(int f_disType ,int f_start,CListCtrl &f_list)
+ExcuteSql(CString f_sql)
+GetTimeWindowList(CListCtrl &f_list)
+ShowTimeWindow(CListCtrl &tdConList, int iTsn)
+GetORGCStringToArray(CString f_SrcString, CStringArray *f_array)
+FreeWindowsTime()
+GetPeriod()
+GetTimeWindowInfo(std : : vector<STSigTWInfo>& vtTWInfo)
+CreateWindowsTime()
+CalculateTimeWindows(struct _WinTimeList f_winTimeList, CStringArray *v_orgData, int f_TRwave, int f_Tcycle, int f_Sample, int f_interation, int f_industrial)
+CalculateTWInfo(CStringArray *v_orgData, int nFrenquence)
+DisplayIpCurveGraph()
}
DataOperator --> TdManager
DataOperator --> TaskDataOper
TaskDataOper --> TdManager
DataOperator --> CTestingData
TaskDataOper --> CTestingData
TdManager --> CTestingData
```
**图源**
- [DataOperator.h](file://h/DataOperator.h)
- [TaskDataOper.h](file://h/TaskDataOper.h)
- [TdManager.h](file://h/TdManager.h)
- [TestingData.h](file://h/TestingData.h)
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 详细组件分析
### DataOperator类分析
DataOperator类是数据操作的核心,负责与数据库的交互,实现数据的读取、写入和管理。通过调用TdManager类的方法,DataOperator能够获取和更新测试数据,并通过TaskDataOper类处理任务数据的序列化和反序列化。DataOperator还支持多种数据格式的导出,包括Excel、CSV、TXT和URF,满足了不同用户的需求。
#### 数据读写与管理
DataOperator通过ADO数据库接口与数据库进行交互,实现了数据的高效读写。在数据读取过程中,DataOperator首先通过SQL查询获取数据记录集,然后将记录集中的数据转换为应用程序内部的数据结构。在数据写入过程中,DataOperator将应用程序内部的数据结构转换为SQL语句,通过执行SQL语句将数据持久化到数据库中。这一过程确保了数据的一致性和完整性。
```mermaid
flowchart TD
Start([开始]) --> CheckConnection["检查数据库连接"]
CheckConnection --> |连接正常| QueryData["执行SQL查询"]
CheckConnection --> |连接异常| HandleError["处理异常"]
QueryData --> ProcessData["处理查询结果"]
ProcessData --> ConvertData["转换为内部数据结构"]
ConvertData --> End([结束])
HandleError --> End
```
**图源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
#### 与TdManager的协同工作
DataOperator与TdManager的协同工作是实现数据管理的关键。TdManager负责测试数据的加载、保存和格式转换,而DataOperator则负责与数据库的交互。当需要加载测试数据时,DataOperator调用TdManager的相应方法,TdManager从数据库中读取数据并返回给DataOperator。当需要保存测试数据时,DataOperator将数据传递给TdManagerTdManager将数据写入数据库。这种协同工作模式确保了数据操作的高效性和可靠性。
```mermaid
sequenceDiagram
participant DataOperator
participant TdManager
participant Database
DataOperator->>TdManager : 请求加载测试数据
TdManager->>Database : 执行SQL查询
Database-->>TdManager : 返回查询结果
TdManager-->>DataOperator : 返回测试数据
DataOperator->>TdManager : 请求保存测试数据
TdManager->>Database : 执行SQL插入
Database-->>TdManager : 确认保存成功
TdManager-->>DataOperator : 确认保存成功
```
**图源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
### TaskDataOper类分析
TaskDataOper类专注于任务数据的操作流程,包括数据的序列化、反序列化及内存管理策略。通过定义一系列方法,TaskDataOper实现了任务数据的高效处理,确保了数据操作的稳定性和可靠性。
#### 任务数据操作流程
TaskDataOper类通过定义一系列方法,实现了任务数据的序列化、反序列化及内存管理。在数据序列化过程中,TaskDataOper将应用程序内部的数据结构转换为适合存储的格式,如JSON或XML。在数据反序列化过程中,TaskDataOper将存储的格式转换回应用程序内部的数据结构。内存管理策略则确保了数据在内存中的高效使用,避免了内存泄漏和性能下降。
```mermaid
flowchart TD
Start([开始]) --> SerializeData["序列化数据"]
SerializeData --> StoreData["存储数据"]
StoreData --> DeserializeData["反序列化数据"]
DeserializeData --> UseData["使用数据"]
UseData --> ManageMemory["管理内存"]
ManageMemory --> End([结束])
```
**图源**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
**节源**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 依赖关系分析
DataOperator模块的依赖关系清晰,主要依赖于TdManager和TaskDataOper两个模块。TdManager负责测试数据的管理,而TaskDataOper负责任务数据的操作。DataOperator通过调用这两个模块的方法,实现了数据的读写和管理。此外,DataOperator还依赖于ADO数据库接口,用于与数据库的交互。这种依赖关系确保了模块间的松耦合,提高了代码的可维护性和可扩展性。
```mermaid
graph TD
DataOperator --> TdManager
DataOperator --> TaskDataOper
DataOperator --> ADO[ADO数据库接口]
TdManager --> ADO
TaskDataOper --> ADO
```
**图源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
**节源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 性能考虑
在设计DataOperator模块时,充分考虑了性能优化。通过批量处理和缓存机制,提高了数据操作的效率。批量处理减少了数据库交互的次数,降低了网络延迟和数据库负载。缓存机制则减少了对数据库的频繁访问,提高了数据读取的速度。此外,通过优化SQL查询语句和索引,进一步提升了数据操作的性能。
## 故障排除指南
### 数据丢失
数据丢失可能是由于数据库连接异常或数据写入失败导致的。在遇到数据丢失问题时,首先检查数据库连接是否正常,然后检查数据写入的日志,确认是否有写入失败的记录。如果发现写入失败,可以尝试重新执行写入操作,或检查数据库的存储空间是否充足。
### 格式不兼容
格式不兼容问题通常出现在数据导出时。在导出数据时,确保选择正确的导出格式,并检查导出文件的编码是否与目标系统兼容。如果遇到格式不兼容问题,可以尝试使用不同的导出工具或转换工具,将数据转换为兼容的格式。
## 结论
DataOperator模块是GeomativeStudio软件中不可或缺的一部分,通过与TdManager和TaskDataOper模块的协同工作,实现了高效的数据读写、处理与管理。该模块不仅支持多种数据格式的导出,还通过批量处理和缓存机制,提高了数据操作的性能。在实际应用中,DataOperator模块展现了其强大的数据处理能力和稳定性,为用户提供了可靠的数据管理解决方案。
@@ -0,0 +1,378 @@
# DeviceOperator
<cite>
**本文引用的文件**
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp)
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
- [DevOperator.h](file://h/DevOperator.h)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp)
- [GD10OperCmd.h](file://h/GD10OperCmd.h)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [Device.h](file://h/Device.h)
- [DevManager.h](file://h/DevManager.h)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文围绕 DeviceOperator 模块,系统阐述 GD10 设备的检测、连接、参数配置与状态监控的实现细节。重点覆盖:
- DetcGD10Dev 如何通过 USB 可移动盘符识别 GD10/GD20 主机并建立“逻辑连接”(挂载路径)。
- DevOperator 如何封装底层指令下发与响应解析,协调 DevManager 完成设备初始化、参数修改、升级流程与状态展示。
- GD10OperCmd 命令协议封装,用于在主机侧模拟对 GD 设备内部文件系统的操作。
- 异常处理与调试方法,安全与权限控制,以及性能优化建议(连接池、异步通信)。
## 项目结构
DeviceOperator 涉及的关键文件与职责如下:
- DetcGD10Dev:设备检测与挂载路径管理,提供“已连接”状态与设备路径。
- DevOperator:设备操作入口,负责树形视图初始化、参数修改、升级流程、权限校验与日志记录。
- GD10OperCmd:命令协议封装,负责在主机侧对 GD 设备内部 XML/文件进行增删改查。
- Device:设备抽象,封装串口命令执行、文件收发、参数读取与状态维护。
- DevManager:设备生命周期与远程设备集合管理。
```mermaid
graph TB
subgraph "设备检测层"
DGD["DetcGD10Dev<br/>检测GD10/GD20设备"]
end
subgraph "设备操作层"
DOp["DevOperator<br/>设备操作入口"]
GOC["GD10OperCmd<br/>命令协议封装"]
end
subgraph "设备抽象层"
Dev["CDevice<br/>串口命令/文件收发"]
DM["DevManager<br/>设备管理"]
end
DGD --> DOp
DOp --> Dev
DOp --> DM
GOC --> DGD
GOC --> Dev
```
图表来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L189)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1-L200)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L120)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
- [DevManager.h](file://h/DevManager.h#L1-L69)
章节来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L189)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1-L200)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L120)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
- [DevManager.h](file://h/DevManager.h#L1-L69)
## 核心组件
- DetcGD10Dev:单例,负责扫描可移动盘符,匹配 GD10/GD20 设备卷标,记录设备路径与连接状态;提供日志输出能力。
- DevOperator:封装设备树初始化、参数修改、升级流程、权限校验与日志记录;与 DevManager 协作完成设备注册/注销与状态展示。
- GD10OperCmd:命令封装,提供工程/测区/脚本/任务的增删改查与参数设置;在主机侧对 GD 内部 XML 文件进行操作。
- CDevice:设备抽象,封装串口命令执行、文件收发、参数读取、状态维护与日志记录;提供“执行命令带轮询”的超时控制。
- DevManager:维护在线/离线设备列表、远程设备集合、设备句柄映射与设备对象生命周期。
章节来源
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h#L1-L38)
- [DevOperator.h](file://h/DevOperator.h#L1-L59)
- [GD10OperCmd.h](file://h/GD10OperCmd.h#L1-L55)
- [Device.h](file://h/Device.h#L1-L128)
- [DevManager.h](file://h/DevManager.h#L1-L69)
## 架构总览
DeviceOperator 的整体交互流程如下:
- 设备检测:DetcGD10Dev 扫描可移动盘符,匹配 GD 设备卷标,返回挂载路径并更新连接状态。
- 设备操作:DevOperator 依据选择的设备项,调用 DevManager 获取设备对象,执行参数修改、升级、权限校验等操作。
- 命令封装:GD10OperCmd 在主机侧对 GD 内部 XML/文件进行增删改查,确保 GD 设备侧数据一致性。
- 设备抽象:CDevice 封装串口命令执行与文件传输,提供超时控制与日志记录。
```mermaid
sequenceDiagram
participant UI as "界面"
participant DO as "DevOperator"
participant DM as "DevManager"
participant D as "CDevice"
participant GD as "GD10OperCmd"
participant DET as "DetcGD10Dev"
UI->>DO : 选择设备项
DO->>DM : GetDeviceByID/GetDevice
DM-->>DO : 返回设备对象
alt 参数修改
DO->>D : ModifyParameter()
D-->>DO : 成功/失败
else 升级流程
DO->>DO : StartDeviceUpgrade()
DO->>D : 执行升级命令/文件传输
D-->>DO : 结果
end
alt 需要主机侧操作
DO->>GD : 调用命令封装
GD->>DET : 读取设备路径
GD-->>DO : 成功/失败
end
```
图表来源
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L384-L433)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1139-L1262)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L51-L105)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L80)
## 详细组件分析
### DetcGD10DevGD10/GD20 设备检测与连接
- 功能要点
- 单例模式,提供 IsGD10DevConnect 与 GetGD10DevAddr 接口。
- 通过扫描 GetLogicalDriveStrings 返回的可移动盘符,匹配 GD10/GD20 卷标或特定路径特征,确定设备挂载路径。
- 提供 CompareDriverName 通过 GetVolumeInformation 获取卷标名进行比对。
- 日志输出到 detect_gd20_log.txt,便于调试设备检测问题。
- 关键流程
- DetectGD10Dev:根据应用多通道配置选择 GD20 或 GD10 设备名,调用 FindUsbDevice 获取路径并更新连接状态。
- FindUsbDevice:遍历可移动盘符,尝试匹配卷标或特定目录特征,返回第一个匹配路径。
- CompareDriverName:读取卷标名并与期望名称比较,返回布尔结果。
- 异常与调试
- 若打开日志失败,弹出提示;若扫描失败,返回空路径。
- 建议:在 UI 层显示检测进度与失败原因,避免静默失败。
```mermaid
flowchart TD
Start(["开始检测"]) --> Scan["扫描可移动盘符"]
Scan --> Match{"匹配GD10/GD20卷标?"}
Match --> |是| Found["返回设备路径"]
Match --> |否| Next["继续扫描下一个盘符"]
Next --> Scan
Found --> Update["更新连接状态与路径"]
Update --> Log["写入检测日志"]
Log --> End(["结束"])
```
图表来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L61-L175)
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L177-L189)
章节来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L189)
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h#L1-L38)
### DevOperator:设备操作入口与与 DevManager 协作
- 功能要点
- 初始化导航设备视图,填充在线/离线/新设备树节点,绑定设备句柄与状态图标。
- 设备升级:创建升级线程,调用 StartDeviceUpgrade,处理升级结果与提示。
- 参数修改:调用设备对象 ModifyParameter 并刷新详情列表。
- 注册/注销:调用设备对象 Register/Unregister,更新树节点与状态。
- 权限校验:GD10 密码校验与数据库密码存储,支持二次确认与日志记录。
- 与 DevManager 协作
- 通过 GetDeviceByID/GetDevice 获取设备对象。
- 添加/删除设备对象,更新树节点与状态。
- 异常与调试
- 创建线程失败、解析设备信息失败等场景均弹出提示并返回失败码。
- 建议:在 UI 中显示升级进度条与错误码,便于定位问题。
```mermaid
sequenceDiagram
participant UI as "界面"
participant DO as "DevOperator"
participant DM as "DevManager"
participant D as "CDevice"
UI->>DO : 点击“注册新设备”
DO->>DM : GetDevice(szDevSN)
DM-->>DO : 返回设备对象
DO->>D : Register()
alt 成功
DO->>DM : AddDevice(pDev)
DO->>DO : 刷新树节点与状态
else 失败
DO-->>UI : 返回失败
end
```
图表来源
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1139-L1262)
- [DevManager.h](file://h/DevManager.h#L1-L69)
章节来源
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1-L200)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1139-L1262)
- [DevOperator.h](file://h/DevOperator.h#L1-L59)
- [DevManager.h](file://h/DevManager.h#L1-L69)
### GD10OperCmd:命令协议封装与主机侧操作
- 功能要点
- 工程/测区/脚本/任务的增删改查,参数设置,用户注销等。
- 通过 DetcGD10Dev 获取 GD 设备挂载路径,直接对 SD 卡内 XML/文件进行操作。
- 对 XML 文件的读取、查找、新增/删除元素、保存等操作均有错误日志记录。
- 关键接口
- project_add/project_delete/testzone_add/testzone_delete/script_add/script_delete/meas_delete/set_param/unregister_user/loadDeviceMarkDataFromGD。
- 安全与日志
- 所有关键操作均记录日志,便于审计与回溯。
- 在非 USB 传输模式下会拒绝执行命令,防止误操作。
```mermaid
classDiagram
class CGD10OperCmd {
+GetInstance()
+project_add(mac, projectcn)
+project_delete(mac, projectcn)
+testzone_add(projectcn, testzonecn, type)
+testzone_delete(projectcn, testzonecn)
+script_add(scriptcn, scriptname, mediumid)
+script_delete(scriptcn)
+meas_delete(projectcn, testzonecn, measuringcn)
+set_param(strParam)
+unregister_user(mac)
+loadDeviceMarkDataFromGD()
-AddProjectInLocalHost()
-AddProjectInMacXml()
-DelProjectInLocalHost()
-DelProjectInMacXml()
-DeleteTaskInTz()
-DeleteTaskFile()
}
class CDetcGD10Dev {
+GetInstance()
+IsGD10DevConnect()
+GetGD10DevAddr()
+DetectGD10Dev()
}
CGD10OperCmd --> CDetcGD10Dev : "使用设备路径"
```
图表来源
- [GD10OperCmd.h](file://h/GD10OperCmd.h#L1-L55)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L120)
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h#L1-L38)
章节来源
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L200)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L800-L1213)
- [GD10OperCmd.h](file://h/GD10OperCmd.h#L1-L55)
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L80)
### CDevice:串口命令执行与文件传输
- 功能要点
- ExecuteOrder/ExecuteSignleOrder:向 GD 设备发送命令并等待特定标志,内置轮询与超时控制。
- SendFile/ReceiveFile:文件上传/下载,支持重试与错误处理。
- GetSynInfo/GetGRInfo/ShowGRInfo/ShowACInfo:数据同步与结果显示。
- Register/Unregister/ModifyParameter/ShowCableHeadInfoDlg:设备注册、参数修改与界面交互。
- 超时与重试
- 默认轮询次数与间隔可配置,避免长时间阻塞。
- 文件传输失败自动重试,提升鲁棒性。
- 日志与状态
- 统一的日志输出接口,便于问题定位。
- 设备状态(在线/离线/新)与图标映射。
```mermaid
flowchart TD
Enter(["进入命令执行"]) --> Clear["清空收发缓冲"]
Clear --> Send["发送命令字符串"]
Send --> Poll["轮询等待标志"]
Poll --> Timeout{"超时/成功?"}
Timeout --> |成功| Parse["解析响应"]
Timeout --> |超时| Retry{"是否重试?"}
Retry --> |是| Send
Retry --> |否| Fail["返回失败"]
Parse --> Done(["返回成功"])
```
图表来源
- [Device.h](file://h/Device.h#L1-L128)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
章节来源
- [Device.h](file://h/Device.h#L1-L128)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L200)
### DevManager:设备生命周期与远程设备管理
- 功能要点
- 在线/离线设备列表获取与管理。
- 远程设备集合(STSigRemoteDev)的增删与查询。
- 设备对象的添加/删除与句柄映射。
- 与 DevOperator 协作
- DevOperator 通过 DevManager 获取设备对象并执行操作。
- 更新远程设备集合,驱动 UI 列表刷新。
章节来源
- [DevManager.h](file://h/DevManager.h#L1-L69)
## 依赖关系分析
- DetcGD10Dev 与 GD10OperCmdGD10OperCmd 在执行前依赖 DetcGD10Dev 的连接状态与设备路径。
- DevOperator 与 DevManager/CDeviceDevOperator 通过 DevManager 获取设备对象,再调用 CDevice 的命令与文件操作。
- GD10OperCmd 与 DetcGD10DevGD10OperCmd 通过 DetcGD10Dev 的单例获取设备挂载路径,直接对 SD 卡内文件进行操作。
- CDevice 与 GD10OperCmd:两者均面向 GD 设备,前者侧重命令与文件传输,后者侧重主机侧对 GD 内部数据结构的维护。
```mermaid
graph LR
DGD["DetcGD10Dev"] --> GOC["GD10OperCmd"]
DOp["DevOperator"] --> DM["DevManager"]
DOp --> Dev["CDevice"]
GOC --> DGD
Dev --> DM
```
图表来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L1-L80)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L120)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1-L200)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
- [DevManager.h](file://h/DevManager.h#L1-L69)
## 性能考量
- 连接池与并发
- 建议为串口通信引入连接池,避免频繁打开/关闭串口导致的握手延迟。
- 对于文件传输与升级流程,采用分块传输与进度回调,减少 UI 卡顿。
- 异步通信
- 将长耗时操作(如升级、文件传输)放入后台线程,主线程仅负责 UI 更新与状态提示。
- 使用事件/消息队列传递结果,避免阻塞 UI 线程。
- 超时与重试策略
- 命令轮询与文件传输应设置合理的超时阈值与重试次数,避免无限等待。
- 对网络不稳定或设备繁忙的情况,增加退避重试与降速策略。
- 缓存与预热
- 对设备参数与常用配置进行缓存,减少重复查询。
- 在设备连接后预热串口与文件传输通道,降低首次操作延迟。
## 故障排查指南
- 设备未检测到
- 检查 DetcGD10Dev 的 DetectGD10Dev 是否返回有效路径;确认卷标名与设备类型匹配。
- 查看 detect_gd20_log.txt 与 device_log.txt 的错误日志。
- 升级失败
- 确认 StartDeviceUpgrade 返回码与提示信息;检查升级包完整性与版本匹配。
- 若 GD10OperCmd 报告文件写入失败,检查 SD 卡空间与权限。
- 命令执行超时
- 调整 CDevice 的轮询次数与间隔;检查串口波特率与线缆质量。
- 对于复杂命令,拆分为多个小命令并增加中间态检查。
- 权限校验失败
- 确认 GD10 密码输入正确;检查数据库中密码记录是否更新成功。
- 若多次失败,建议清理缓存并重新输入。
- 文件传输失败
- 检查 SD 卡路径是否存在;确认文件名大小写与扩展名一致。
- 增加重试次数与断点续传机制。
章节来源
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L177-L189)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1-L120)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L1517-L1599)
- [GD10OperCmd.cpp](file://cpp/Tools/GD10OperCmd.cpp#L1-L120)
## 结论
DeviceOperator 模块通过 DetcGD10Dev 的设备检测、DevOperator 的操作编排、GD10OperCmd 的命令封装与 CDevice 的底层通信,形成了完整的 GD10 设备管理闭环。模块具备良好的日志记录与异常处理能力,建议进一步引入连接池、异步通信与缓存机制,以提升性能与用户体验。
## 附录
- 安全性建议
- 权限验证:GD10 密码校验与数据库存储,避免未授权访问。
- 操作审计:所有关键操作均写入日志,便于追踪与回溯。
- 输入校验:对命令参数与文件路径进行严格校验,防止注入与越权。
- 性能优化清单
- 串口连接池与复用。
- 异步升级与文件传输。
- 超时与重试策略优化。
- UI 进度反馈与中断机制。
@@ -0,0 +1,225 @@
# ExecutionOperator
<cite>
**本文档中引用的文件**
- [ExecOperator.cpp](file://cpp/Operator/ExecOperator.cpp)
- [ExecOperator.h](file://h/ExecOperator.h)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp)
- [ExecManager.h](file://h/ExecManager.h)
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp)
- [DialMeasureData.h](file://h/DialMeasureData.h)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TaskDataOper.h](file://h/TaskDataOper.h)
- [DialOfflineDeviceTaskManager.cpp](file://cpp/Views/DialOfflineDeviceTaskManager.cpp)
- [DialOfflineDeviceTaskManager.h](file://h/DialOfflineDeviceTaskManager.h)
</cite>
## 目录
1. [引言](#引言)
2. [ExecutionOperator职责与实现](#executionoperator职责与实现)
3. [与ExecManager的协作机制](#与execmanager的协作机制)
4. [用户交互事件处理流程](#用户交互事件处理流程)
5. [异常情况恢复策略](#异常情况恢复策略)
6. [性能监控指标与优化建议](#性能监控指标与优化建议)
7. [离线模式执行任务的实现细节](#离线模式执行任务的实现细节)
8. [结论](#结论)
## 引言
ExecutionOperator是Geomative Studio系统中负责测量任务执行过程的核心组件。它协调设备、脚本和数据管理组件,完成测量任务的启动、暂停、恢复和终止。本文档详细阐述了ExecutionOperator的职责与实现,说明其如何与ExecManager协作管理任务状态机、实时数据采集和进度反馈,并结合UI组件(如DialMeasureData)说明用户交互事件的处理流程。此外,文档还提供了任务执行过程中异常情况的恢复策略、性能监控指标与优化建议,以及支持离线模式执行任务的实现细节。
## ExecutionOperator职责与实现
ExecutionOperator的主要职责是协调设备、脚本和数据管理组件,完成测量任务的启动、暂停、恢复和终止。它通过ExecManager与底层设备进行通信,确保测量任务的顺利执行。
ExecutionOperator的实现主要集中在`ExecOperator.cpp``ExecOperator.h`文件中。`CExecOperator`类的构造函数接受一个数据库连接指针,用于与数据库进行交互。`ExecRSPTest`方法是执行电阻率测试的入口点,它创建并初始化`COpExec2DRSPTestSetDlg`对话框,然后根据用户选择的测试类型调用ExecManager的相应方法。
```mermaid
classDiagram
class CExecOperator {
+CExecOperator(_ConnectionPtr& pConnection)
+~CExecOperator()
+ExecRSPTest()
+InitialExec2DRSPTestDlg(COpExec2DRSPTestSetDlg* pOpExec2DRSPTestSetDlg)
}
class COpExec2DRSPTestSetDlg {
+Create()
+ShowWindow()
+RunModalLoop()
+DestroyWindow()
}
CExecOperator --> COpExec2DRSPTestSetDlg : "创建并初始化"
```
**Diagram sources**
- [ExecOperator.cpp](file://cpp/Operator/ExecOperator.cpp#L26-L72)
- [ExecOperator.h](file://h/ExecOperator.h#L23-L26)
**Section sources**
- [ExecOperator.cpp](file://cpp/Operator/ExecOperator.cpp#L1-L72)
- [ExecOperator.h](file://h/ExecOperator.h#L1-L37)
## 与ExecManager的协作机制
ExecutionOperator与ExecManager紧密协作,共同完成测量任务的管理。ExecManager负责具体的任务执行逻辑,包括初始化测量、发送测量命令和处理测量结果。
`CExecManager`类提供了`Exec2DRSPTest``ExecCERSPTest`方法,分别用于执行2D和1D电阻率测试。这些方法首先创建相应的测量数据对象(`CRsp2DTd``CRspCETd`),然后调用`Save2DRSPSetInfo``SaveCERSPSetInfo`方法将测量设置信息保存到对象中。接着,将测量头信息保存到文件,并通过设备的`SendFile`方法将文件发送到主机。最后,调用`InitialMeasure`方法初始化测量,并创建相应的测量对话框(`COpExec2DRSPTestDlg``COpExecCERSPTestDlg`)来显示测量进度。
```mermaid
sequenceDiagram
participant ExecutionOperator
participant ExecManager
participant Device
participant MeasurementDialog
ExecutionOperator->>ExecManager : Exec2DRSPTest()
ExecManager->>ExecManager : 创建CRsp2DTd对象
ExecManager->>ExecManager : 保存测量设置信息
ExecManager->>ExecManager : 保存头信息到文件
ExecManager->>Device : SendFile()
Device-->>ExecManager : 文件发送成功
ExecManager->>ExecManager : InitialMeasure()
ExecManager->>MeasurementDialog : 创建并显示对话框
MeasurementDialog-->>ExecManager : 测量完成
ExecManager-->>ExecutionOperator : 返回结果
```
**Diagram sources**
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L483-L548)
- [ExecManager.h](file://h/ExecManager.h#L26-L27)
**Section sources**
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L483-L548)
- [ExecManager.h](file://h/ExecManager.h#L26-L27)
## 用户交互事件处理流程
用户交互事件的处理主要由`DialMeasureData`类负责。该类处理用户在测量界面上的各种操作,如启动测量、暂停测量、从当前位置继续测量等。
`CDialMeasureData`类的`OnMeasureAll`方法处理“启动测量”按钮的点击事件。它首先检查是否已经下载了测量配置,如果没有,则调用`OnMeasureDownloadMeasuCfg`方法下载配置。然后,更新任务的测试日期和时间,并根据测量类型打开相应的数据表。最后,设置按钮状态,准备开始测量。
```mermaid
flowchart TD
Start([开始测量]) --> CheckDownload{"已下载配置?"}
CheckDownload --> |否| Download[下载测量配置]
Download --> UpdateTime[更新测试日期和时间]
CheckDownload --> |是| UpdateTime
UpdateTime --> OpenTable{"测量类型"}
OpenTable --> |数据| OpenData[打开数据表]
OpenTable --> |接地电阻| ClearGR[清除接地电阻信息]
OpenData --> SetStatus[设置按钮状态]
ClearGR --> SetStatus
SetStatus --> End([准备测量])
```
**Diagram sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L378-L497)
- [DialMeasureData.h](file://h/DialMeasureData.h#L61-L64)
**Section sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L378-L497)
- [DialMeasureData.h](file://h/DialMeasureData.h#L61-L64)
## 异常情况恢复策略
在测量过程中,可能会遇到各种异常情况,如设备断开、数据校验失败等。系统提供了一系列恢复策略来应对这些异常。
当设备断开时,系统会尝试重新连接设备。如果重新连接失败,会显示错误消息并终止测量。对于数据校验失败的情况,系统会记录错误日志,并尝试重新发送数据包。如果多次尝试后仍然失败,会终止测量并提示用户检查设备连接。
```mermaid
stateDiagram-v2
[*] --> Idle
Idle --> Measuring : "启动测量"
Measuring --> DeviceDisconnected : "设备断开"
Measuring --> DataValidationFailed : "数据校验失败"
DeviceDisconnected --> Reconnect : "尝试重新连接"
Reconnect --> Measuring : "连接成功"
Reconnect --> Error : "连接失败"
DataValidationFailed --> Retry : "重新发送"
Retry --> Measuring : "发送成功"
Retry --> Error : "重试次数超限"
Error --> Idle : "终止测量"
Measuring --> Completed : "测量完成"
Completed --> Idle : "结束"
```
**Diagram sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L928-L1100)
- [DialMeasureData.h](file://h/DialMeasureData.h#L80-L81)
**Section sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L928-L1100)
- [DialMeasureData.h](file://h/DialMeasureData.h#L80-L81)
## 性能监控指标与优化建议
系统提供了多种性能监控指标,包括采样频率、响应延迟等。这些指标可以帮助用户评估测量过程的性能,并进行相应的优化。
采样频率是指每秒采集的数据点数,它直接影响测量的精度和速度。响应延迟是指从发送测量命令到接收到测量结果的时间间隔,它反映了系统的实时性。
为了优化性能,建议采取以下措施:
1. 使用高速通信接口,如USB或以太网,以减少通信延迟。
2. 优化数据处理算法,减少CPU占用率。
3. 使用高效的数据库查询语句,减少数据访问时间。
4. 定期维护设备,确保设备处于最佳工作状态。
```mermaid
erDiagram
MEASUREMENT ||--o{ PERFORMANCE_METRICS : "包含"
PERFORMANCE_METRICS {
float sampling_frequency
float response_latency
float cpu_usage
float memory_usage
}
OPTIMIZATION_STRATEGIES ||--o{ PERFORMANCE_METRICS : "优化"
OPTIMIZATION_STRATEGIES {
string high_speed_interface
string optimized_algorithm
string efficient_query
string regular_maintenance
}
```
**Diagram sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L948-L954)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L4314-L4332)
**Section sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L948-L954)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L4314-L4332)
## 离线模式执行任务的实现细节
系统支持离线模式执行任务,允许用户在没有网络连接的情况下进行测量。离线模式的实现主要依赖于`DialOfflineDeviceTaskManager`类。
在离线模式下,测量数据首先保存在本地数据库中。当网络连接恢复后,用户可以手动上传数据到服务器。`CDialOfflineDeviceTaskManager`类提供了创建、删除、上传和管理离线任务的功能。
```mermaid
classDiagram
class CDialOfflineDeviceTaskManager {
+OnButtonCreateTask()
+OnButtonDelTask()
+OnButtonMeasureTask()
+OnBtnDataDownload()
+OnBtnCreateTimerTask()
+OnBtnManageTimerTask()
}
class CTaskDataOper {
+Create1DTask()
+Create2DTask()
+Create3DTask()
+DeleteTaskArray()
+InsertPlcStatusData()
}
CDialOfflineDeviceTaskManager --> CTaskDataOper : "使用"
```
**Diagram sources**
- [DialOfflineDeviceTaskManager.cpp](file://cpp/Views/DialOfflineDeviceTaskManager.cpp#L323-L325)
- [TaskDataOper.h](file://h/TaskDataOper.h#L344-L346)
**Section sources**
- [DialOfflineDeviceTaskManager.cpp](file://cpp/Views/DialOfflineDeviceTaskManager.cpp#L323-L325)
- [TaskDataOper.h](file://h/TaskDataOper.h#L344-L346)
## 结论
ExecutionOperator是Geomative Studio系统中测量任务执行的核心组件。它通过与ExecManager的紧密协作,实现了测量任务的启动、暂停、恢复和终止。系统提供了完善的用户交互事件处理流程、异常情况恢复策略、性能监控指标与优化建议,以及支持离线模式执行任务的实现细节。这些功能共同确保了测量任务的高效、可靠执行。
@@ -0,0 +1,168 @@
# Operator模块
<cite>
**Referenced Files in This Document**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DataOperator.h](file://h/DataOperator.h)
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp)
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
- [DevOperator.h](file://h/DevOperator.h)
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptOperator.h](file://h/SptOperator.h)
- [ExecOperator.cpp](file://cpp/Operator/ExecOperator.cpp)
- [ExecOperator.h](file://h/ExecOperator.h)
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp)
- [SynOperator.h](file://h/SynOperator.h)
- [InputPasswordDial.cpp](file://cpp/Operator/InputPasswordDial.cpp)
- [InputPasswordDial.h](file://h/InputPasswordDial.h)
- [DialCustomSptInput.cpp](file://cpp/Operator/DialCustomSptInput.cpp)
- [DialCustomSptInput.h](file://h/DialCustomSptInput.h)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [UpdateDataBase.h](file://h/UpdateDataBase.h)
</cite>
## 目录
1. [DataOperator数据操作器](#dataoperator数据操作器)
2. [DetcGD10Dev设备检测器](#detcgd10dev设备检测器)
3. [DevOperator设备操作器](#devoperator设备操作器)
4. [SptOperator脚本操作器](#sptoperator脚本操作器)
5. [ExecOperator执行操作器](#execoperator执行操作器)
6. [SynOperator同步操作器](#synoperator同步操作器)
7. [对话框操作器](#对话框操作器)
8. [UpdateDataBase数据库升级器](#updatedatabase数据库升级器)
9. [操作器与管理器调用关系](#操作器与管理器调用关系)
## DataOperator数据操作器
DataOperator类负责处理应用程序中的数据读写操作,主要功能包括初始化导航数据视图、显示各类测试数据信息以及在数据库中创建和删除项目。该操作器通过ADO数据库连接与后端数据库进行交互,使用`_ConnectionPtr`对象管理数据库连接。
`InitialNavDataView`方法负责初始化导航数据视图,通过查询数据库中的项目(project)、测区(tz)和测试任务(td)表,构建树形结构的数据视图。该方法首先获取项目信息,然后为每个项目获取其下属的测区,最后为每个测区获取其包含的测试任务。在构建树形结构时,使用`CHandleProcessor`生成唯一句柄,并通过`CStateProcessor`设置节点状态图像。
数据展示功能通过一系列`ShowXxxInfo`方法实现,如`ShowProjectInfo``ShowTzInfo``ShowRsp3DTdInfo`等。这些方法通过调用管理器对象(如`theApp.m_pProManager``theApp.m_pTdManager`)获取相应的数据对象,并调用其`ShowDetailInfo``ShowConList`等方法将数据显示在相应的视图控件中。
数据库操作方面,`CreateProjectInDB`方法在数据库中创建新项目,通过事务处理确保数据一致性。该方法首先调用`ProManager``CreateProjectInDB`方法在数据库中创建项目记录,然后更新导航视图以反映新创建的项目。类似地,`DeleteProjectInDB`方法用于删除项目及其相关数据。
**Section sources**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L241-L486)
- [DataOperator.h](file://h/DataOperator.h#L96-L171)
## DetcGD10Dev设备检测器
DetcGD10Dev类负责检测GD10设备的连接状态,采用单例模式实现,确保在整个应用程序中只有一个实例存在。该类通过USB设备枚举机制检测特定名称的可移动驱动器来识别GD10设备。
`DetectGD10Dev`方法是设备检测的核心,它调用`FindUsbDevice`方法搜索系统中的USB设备。搜索过程首先获取系统中所有逻辑驱动器,然后遍历这些驱动器,识别类型为`DRIVE_REMOVABLE`(可移动驱动器)的设备。对于每个可移动驱动器,通过`CompareDriverName`方法验证其卷标名称是否匹配预期的设备名称("GD10"或"GD20")。
`CompareDriverName`方法不仅检查卷标名称,还提供了备用检测机制。当卷标名称不匹配时,会检查驱动器根目录下是否存在"\SD\equipment"目录,这种设计提高了设备识别的可靠性,避免了因卷标名称修改导致的识别失败。
设备检测结果通过`m_bGD10DevIsCon`布尔变量和`m_strDevAddr`字符串变量存储,分别表示设备是否连接和设备的驱动器路径。检测过程中的日志信息通过`PrintLog`方法写入"log\detect_gd20_log.txt"文件,便于问题排查和调试。
**Section sources**
- [DetcGD10Dev.cpp](file://cpp/Operator/DetcGD10Dev.cpp#L61-L68)
- [DetcGD10Dev.h](file://h/DetcGD10Dev.h#L22-L24)
## DevOperator设备操作器
DevOperator类负责执行与设备相关的各种操作,包括初始化设备导航视图、显示设备信息、设备升级和参数修改等。该操作器管理在线和离线设备的显示,通过树形结构组织设备信息。
`InitialNavDevView`方法构建设备导航视图的树形结构,分为在线设备和离线设备两大分支。在线设备进一步分为已注册设备和新发现设备。该方法通过`DevManager`获取设备列表,并根据设备状态(在线、离线、新设备)将其添加到相应的树节点中。设备信息的显示使用`m_handleProcessor`生成的句柄进行标识。
设备信息展示功能通过`ShowFLDeviceInfo``ShowOLDeviceInfo`方法实现,分别用于显示离线和在线设备的详细信息。这些方法调用`DevManager`获取设备对象,并调用其`ShowFLDetailInfo``ShowOLDetailInfo`等方法将设备参数、接地电阻信息等数据显示在相应的视图控件中。
设备管理功能包括`DevieUpgrade`(设备升级)、`ModifyDeviceParameter`(修改设备参数)和`ShowCableHeadDlg`(显示电缆头对话框)等。设备升级操作通过创建独立线程执行,避免阻塞用户界面。`RefreshGRRec``RefreshAllGRRec`方法用于刷新设备的接地电阻记录,通过与设备通信获取最新的接地电阻测量数据。
**Section sources**
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L60-L331)
- [DevOperator.h](file://h/DevOperator.h#L23-L47)
## SptOperator脚本操作器
SptOperator类负责处理脚本相关的操作,包括初始化脚本导航视图、显示脚本信息以及在数据库中创建和管理脚本。该操作器支持一维(CE)、二维(2D)和三维(3D)三种类型的脚本。
`InitialNavExecView`方法初始化脚本导航视图,依次调用`InitialNavExecCEDlg``InitialNavExec2DDlg``InitialNavExec3DDlg`方法初始化不同类型脚本的对话框。这些初始化方法通过查询数据库中的`scon`表获取已存在的脚本列表,并将其显示在相应的列表控件中。
脚本信息展示通过`ShowCEScriptConInfo``Show2DScriptConInfo``Show3DScriptConInfo`方法实现。这些方法首先通过`SptManager`获取脚本对象,然后调用其`ShowSptDetailInfo``ShowChannelList``ShowSptConInfo`方法将脚本的详细信息、通道列表和测量序列数据显示在相应的视图控件中。
脚本管理功能包括`Create2DSConInDB``Create3DSConInDB``CreateCESConInDB`等方法,用于在数据库中创建新的脚本。创建成功后,通过`AddSConItemToSConList`方法将新脚本添加到相应的列表控件中。`Export2DSConInDB``Export3DSConInDB`方法支持将脚本导出为文本文件。
**Section sources**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp#L43-L791)
- [SptOperator.h](file://h/SptOperator.h#L33-L45)
## ExecOperator执行操作器
ExecOperator类负责执行测量任务,主要功能是启动电阻率测试。`ExecRSPTest`方法是执行测量任务的核心,它创建并显示`COpExec2DRSPTestSetDlg`对话框,让用户配置测试参数。
`InitialExec2DRSPTestSetDlg`方法初始化测试设置对话框,填充各种参数选项。该方法查询数据库中的`cm`表获取参数的可选值,如电极排列方式(`Clayout`)、发射频率(`Trfrequency`)、采样频率(`SAfrequency50`)等。这些参数根据当前语言设置进行本地化显示。
当用户完成参数配置并确认后,`ExecRSPTest`方法根据用户选择的标签页(一维或二维)调用`ExecManager`的相应方法执行测试。对于一维测试,调用`ExecCERSPTest`;对于二维测试,调用`Exec2DRSPTest`。测试执行完成后,对话框被销毁。
**Section sources**
- [ExecOperator.cpp](file://cpp/Operator/ExecOperator.cpp#L37-L213)
- [ExecOperator.h](file://h/ExecOperator.h#L26-L27)
## SynOperator同步操作器
SynOperator类负责处理同步操作,主要功能是启动同步对话框。`Syn`方法创建并显示`COpSynDlg`对话框,允许用户选择要同步的设备。
`InitialSynDlg`方法初始化同步对话框,通过`DevManager`获取在线设备列表,并将设备序列号添加到设备选择下拉框中。该方法只显示状态为"在线"而非"新设备"的设备,确保用户只能选择已注册的设备进行同步。
同步操作本身在`COpSynDlg`对话框中实现,`SynOperator`主要负责对话框的初始化和显示。当用户完成同步设置并确认后,同步过程开始;如果用户取消操作,则对话框被销毁。
**Section sources**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp#L32-L81)
- [SynOperator.h](file://h/SynOperator.h#L17-L18)
## 对话框操作器
### InputPasswordDial密码输入对话框
InputPasswordDial类实现密码输入对话框,用于用户身份验证。该对话框支持两种验证模式:直接验证和GD10验证,通过`m_bIsDirectVerify`标志区分。
`OnOK`方法处理用户确认操作,首先验证输入的密码是否为空,然后根据验证模式检查密码是否正确。在直接验证模式下,将输入密码与预设的Geomative密码进行比较;在GD10验证模式下,跳过密码检查。密码验证通过后,调用基类的`OnOK`方法关闭对话框。
`OnInitDialog`方法初始化对话框,根据验证模式设置窗口标题和提示信息。如果处于直接验证模式但未设置密码,则显示错误消息并拒绝初始化。`OnCancel`方法处理用户取消操作,显示确认对话框询问用户是否确实要放弃输入密码。
**Section sources**
- [InputPasswordDial.cpp](file://cpp/Operator/InputPasswordDial.cpp#L47-L108)
- [InputPasswordDial.h](file://h/InputPasswordDial.h#L38-L40)
### DialCustomSptInput自定义脚本输入对话框
DialCustomSptInput类实现自定义脚本输入对话框,允许用户手动输入或从Excel文件导入脚本参数。该对话框支持两种K值计算模式:手动输入和自动计算。
`OnButtonAddList`方法处理添加脚本行操作,首先验证输入的有效性,然后计算K值(如果处于自动计算模式),最后将参数添加到列表控件中。`CheckInputIsValid`方法验证所有输入字段,确保A、B、M、N、层数和迭代数为正整数或-1,K值为有效浮点数。
`CalculateK`方法在自动计算模式下根据A、B、M、N电极位置计算几何因子K。计算公式基于电极间距离的倒数差,考虑了无穷远电极(用-1表示)的特殊情况。`OnButtonImport`方法支持从Excel文件导入脚本数据,使用COM接口与Excel应用程序交互,读取指定工作表中的数据。
**Section sources**
- [DialCustomSptInput.cpp](file://cpp/Operator/DialCustomSptInput.cpp#L78-L757)
- [DialCustomSptInput.h](file://h/DialCustomSptInput.h#L48-L56)
## UpdateDataBase数据库升级器
UpdateDataBase类负责处理数据库升级,通过解析XML配置文件执行数据库结构的变更。该类在应用程序启动时检查当前数据库版本,并根据需要执行升级操作。
`ParserUpdateDBXml`方法解析"updates\database_modify.xml"文件,查找与当前软件版本匹配的升级记录。该方法首先验证当前版本与XML文件中声明的版本是否一致,然后查找前一版本的升级信息。`GetDBUpdatesInfo`方法解析具体的数据库变更指令,包括创建表、删除表和修改表结构。
数据库操作通过`AddDBTable``DeleteDBTable``ModifyDBTable`方法实现。`AddDBTable`方法根据`STTableInfo`结构中的信息生成CREATE TABLE SQL语句,包括列定义、主键、索引和外键约束。`ModifyDBTable`方法处理表结构修改,支持添加列、删除列和修改列属性。
`UpdateDBInfo`方法是数据库升级的入口点,按顺序执行所有收集的数据库变更操作。升级完成后,调用`WriteVersionToDB`方法更新数据库中的版本信息,确保下次启动时不会重复执行已应用的升级。
**Section sources**
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp#L432-L873)
- [UpdateDataBase.h](file://h/UpdateDataBase.h#L76-L97)
## 操作器与管理器调用关系
操作器与管理器之间存在紧密的调用关系,操作器作为管理器功能的前端接口,将用户操作转化为对管理器的具体调用。这种设计模式实现了关注点分离,操作器负责用户界面交互,管理器负责核心业务逻辑。
以SptManager调用SptOperator为例,当用户在脚本管理界面创建新脚本时,SptManager的`Create2DSConInDB`方法被调用。该方法执行核心的脚本创建逻辑,包括在数据库中插入记录和在内存中创建脚本对象。创建成功后,控制权返回给SptOperator,由其调用`AddSConItemToSConList`方法更新用户界面,将新脚本显示在列表中。
类似地,DevOperator在设备升级操作中调用DevManager的功能。`DevieUpgrade`方法首先获取选中的设备句柄,然后通过`DevManager``GetDeviceByID`方法获取设备对象。升级操作在独立线程中执行,调用`StartDeviceUpgrade`函数,该函数最终会调用DevManager中的设备通信和固件更新逻辑。
这种调用关系体现了典型的MVCModel-View-Controller)模式,其中管理器扮演Model角色,负责数据和业务逻辑;操作器扮演Controller角色,处理用户输入并协调Model和View;视图类(如各种CView派生类)则负责数据显示。通过这种分层架构,系统实现了良好的模块化和可维护性。
**Section sources**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp#L497-L522)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L385-L433)
@@ -0,0 +1,253 @@
# ScriptOperator
<cite>
**本文档中引用的文件**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [Script3D.cpp](file://cpp/ProblemZone/Script3D.cpp)
- [ScriptCE.cpp](file://cpp/ProblemZone/ScriptCE.cpp)
- [SptManager.h](file://h/SptManager.h)
- [SptOperator.h](file://h/SptOperator.h)
- [Script.h](file://h/Script.h)
- [Script2D.h](file://h/Script2D.h)
- [Script3D.h](file://h/Script3D.h)
- [ScriptCE.h](file://h/ScriptCE.h)
- [Medium.h](file://h/Medium.h)
- [MediumBasicWenAndSch.h](file://h/MediumBasicWenAndSch.h)
- [MediumStrongWenAndSch.h](file://h/MediumStrongWenAndSch.h)
- [MediumCrossHoleGeomative.h](file://h/MediumCrossHoleGeomative.h)
- [MediumCustom2D.h](file://h/MediumCustom2D.h)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
ScriptOperator是Geomative Studio软件中负责脚本生成与管理的核心组件,主要处理2D、3D及跨孔测量脚本的创建、编辑和导出功能。该组件与SptManager协同工作,根据用户配置生成相应的测量脚本,包括电极排列计算、测量序列生成和脚本验证逻辑。ScriptOperator支持多种测量模式,如温纳法、施伦贝尔格法等,并提供脚本格式的内部结构说明和性能优化策略。
## 项目结构
Geomative Studio项目包含多个目录,其中与ScriptOperator相关的文件主要位于`cpp/Operator``cpp/Managers`目录下。`cpp/Operator`目录包含SptOperator.cpp,负责脚本操作的具体实现;`cpp/Managers`目录包含SptManager.cpp,负责脚本的管理和协调。此外,`cpp/ProblemZone`目录包含各种脚本类的实现文件,如Script2D.cpp、Script3D.cpp等。
```mermaid
graph TD
subgraph "核心组件"
SptOperator["SptOperator.cpp"]
SptManager["SptManager.cpp"]
end
subgraph "脚本实现"
Script2D["Script2D.cpp"]
Script3D["Script3D.cpp"]
ScriptCE["ScriptCE.cpp"]
end
subgraph "介质类"
Medium["Medium.h"]
MediumBasic["MediumBasicWenAndSch.h"]
MediumStrong["MediumStrongWenAndSch.h"]
MediumCrossHole["MediumCrossHoleGeomative.h"]
MediumCustom["MediumCustom2D.h"]
end
SptOperator --> SptManager
SptManager --> Script2D
SptManager --> Script3D
SptManager --> ScriptCE
Script2D --> MediumBasic
Script2D --> MediumStrong
Script3D --> MediumCrossHole
ScriptCE --> MediumCustom
```
**图源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [Script3D.cpp](file://cpp/ProblemZone/Script3D.cpp)
- [ScriptCE.cpp](file://cpp/ProblemZone/ScriptCE.cpp)
- [Medium.h](file://h/Medium.h)
- [MediumBasicWenAndSch.h](file://h/MediumBasicWenAndSch.h)
- [MediumStrongWenAndSch.h](file://h/MediumStrongWenAndSch.h)
- [MediumCrossHoleGeomative.h](file://h/MediumCrossHoleGeomative.h)
- [MediumCustom2D.h](file://h/MediumCustom2D.h)
**节源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 核心组件
ScriptOperator的核心功能包括创建、删除和导出2D、3D及跨孔测量脚本。通过与SptManager的交互,ScriptOperator能够根据用户配置生成相应的脚本,并处理脚本生成过程中的常见错误,如电极冲突和参数越界。SptManager负责管理脚本的生命周期,包括脚本的创建、编辑和导出。
**节源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 架构概述
ScriptOperator与SptManager之间的调用关系如下图所示。SptOperator负责用户界面的交互,接收用户输入并调用SptManager的方法来创建、删除和导出脚本。SptManager则负责具体的脚本生成逻辑,包括电极排列计算、测量序列生成和脚本验证。
```mermaid
sequenceDiagram
participant 用户 as "用户"
participant SptOperator as "SptOperator"
participant SptManager as "SptManager"
participant 脚本类 as "脚本类"
用户->>SptOperator : 创建新脚本
SptOperator->>SptManager : 调用Create2DSConInDB
SptManager->>脚本类 : 生成脚本
脚本类-->>SptManager : 返回脚本ID
SptManager-->>SptOperator : 返回执行结果
SptOperator-->>用户 : 显示结果
用户->>SptOperator : 编辑现有脚本
SptOperator->>SptManager : 调用EditScript
SptManager->>脚本类 : 修改脚本
脚本类-->>SptManager : 返回修改结果
SptManager-->>SptOperator : 返回执行结果
SptOperator-->>用户 : 显示结果
用户->>SptOperator : 导出脚本
SptOperator->>SptManager : 调用Export2DSConInDB
SptManager->>脚本类 : 导出脚本
脚本类-->>SptManager : 返回导出结果
SptManager-->>SptOperator : 返回执行结果
SptOperator-->>用户 : 显示结果
```
**图源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
**节源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 详细组件分析
### ScriptOperator分析
ScriptOperator的主要职责是处理用户界面的交互,接收用户输入并调用SptManager的方法来执行具体的操作。例如,当用户创建新脚本时,SptOperator会调用SptManager的Create2DSConInDB方法来生成脚本。
```mermaid
classDiagram
class CSptOperator {
+InitialNavExecView(CNavSptView* pNavExecView)
+ShowCEScriptConInfo(DWORD dwSptHandle, CView* pAppExecView)
+Show2DScriptConInfo(DWORD dwSptHandle, CView* pAppExecView)
+Show3DScriptConInfo(DWORD dwSptHandle, CView* pAppExecView)
+Create2DSConInDB(CNavSptView* pNavExecView)
+Delete2DSConInDB(CNavSptView* pNavExecView)
+Export2DSConInDB(CNavSptView* pNavExecView)
+CreateCESConInDB(CNavSptView* pNavExecView)
+DeleteCESConInDB(CNavSptView* pNavExecView)
+Create3DSConInDB(CNavSptView* pNavExecView)
+Delete3DSConInDB(CNavSptView* pNavExecView)
}
class CSptManager {
+Create2DSConInDB(DWORD& dwSConID)
+Delete2DSConInDB(DWORD dwSConID)
+Export2DSConInDB(DWORD dwSConID, CString strSptFilePath)
+CreateCESConInDB(DWORD& dwSConID)
+DeleteCESConInDB(DWORD dwSConID)
+Create3DSConInDB(DWORD dwSConID[128])
+Delete3DSConInDB(DWORD dwSConID)
}
CSptOperator --> CSptManager : "调用"
```
**图源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
**节源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
### 脚本生成逻辑分析
脚本生成过程中,SptManager会根据用户选择的测量模式(如温纳法、施伦贝尔格法等)生成相应的电极排列和测量序列。不同的测量模式有不同的实现类,如MediumBasicWenAndSch、MediumStrongWenAndSch等。
```mermaid
flowchart TD
Start([开始]) --> 选择测量模式
选择测量模式 --> 生成电极排列
生成电极排列 --> 生成测量序列
生成测量序列 --> 验证脚本
验证脚本 --> 保存脚本
保存脚本 --> 结束([结束])
验证脚本 --> |电极冲突| 处理错误
验证脚本 --> |参数越界| 处理错误
处理错误 --> 重新生成
重新生成 --> 生成电极排列
```
**图源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [MediumBasicWenAndSch.h](file://h/MediumBasicWenAndSch.h)
- [MediumStrongWenAndSch.h](file://h/MediumStrongWenAndSch.h)
- [MediumCrossHoleGeomative.h](file://h/MediumCrossHoleGeomative.h)
- [MediumCustom2D.h](file://h/MediumCustom2D.h)
**节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [MediumBasicWenAndSch.h](file://h/MediumBasicWenAndSch.h)
- [MediumStrongWenAndSch.h](file://h/MediumStrongWenAndSch.h)
- [MediumCrossHoleGeomative.h](file://h/MediumCrossHoleGeomative.h)
- [MediumCustom2D.h](file://h/MediumCustom2D.h)
## 依赖关系分析
ScriptOperator依赖于SptManager来执行具体的脚本生成逻辑,而SptManager又依赖于各种脚本类和介质类来生成具体的测量脚本。这种分层架构使得各个组件之间的职责清晰,便于维护和扩展。
```mermaid
graph TD
SptOperator --> SptManager
SptManager --> Script2D
SptManager --> Script3D
SptManager --> ScriptCE
Script2D --> MediumBasic
Script2D --> MediumStrong
Script3D --> MediumCrossHole
ScriptCE --> MediumCustom
```
**图源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [Script3D.cpp](file://cpp/ProblemZone/Script3D.cpp)
- [ScriptCE.cpp](file://cpp/ProblemZone/ScriptCE.cpp)
- [MediumBasicWenAndSch.h](file://h/MediumBasicWenAndSch.h)
- [MediumStrongWenAndSch.h](file://h/MediumStrongWenAndSch.h)
- [MediumCrossHoleGeomative.h](file://h/MediumCrossHoleGeomative.h)
- [MediumCustom2D.h](file://h/MediumCustom2D.h)
**节源**
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 性能考虑
为了提高脚本生成的性能,SptManager采用了缓存机制来存储常用的计算结果。例如,电极排列和测量序列的计算结果会被缓存,以避免重复计算。此外,SptManager还支持多线程操作,可以在后台线程中执行耗时的计算任务,从而提高用户体验。
**节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 故障排除指南
在脚本生成过程中,可能会遇到电极冲突和参数越界等常见错误。SptManager提供了相应的错误处理机制,可以在生成脚本时检测并处理这些错误。例如,当检测到电极冲突时,SptManager会提示用户重新配置电极排列。
**节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 结论
ScriptOperator是Geomative Studio中负责脚本生成与管理的核心组件,通过与SptManager的协同工作,能够根据用户配置生成2D、3D及跨孔测量脚本。该组件支持多种测量模式,并提供了脚本格式的内部结构说明和性能优化策略。通过合理的架构设计和错误处理机制,ScriptOperator能够高效地生成和管理测量脚本,满足用户的需求。
@@ -0,0 +1,299 @@
# SynchronizationOperator
<cite>
**本文档中引用的文件**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp)
- [SynOperator.h](file://h/SynOperator.h)
- [opsyndlg.cpp](file://cpp/Views/opsyndlg.cpp)
- [opsyndlg.h](file://h/opsyndlg.h)
- [opsyntddlg.cpp](file://cpp/Views/opsyntddlg.cpp)
- [opsyntddlg.h](file://h/opsyntddlg.h)
- [opsynsptdlg.cpp](file://cpp/Views/opsynsptdlg.cpp)
- [opsynsptdlg.h](file://h/opsynsptdlg.h)
- [OperMediumPt.cpp](file://cpp/Operator/OperMediumPt.cpp)
- [OperMediumPt.h](file://h/OperMediumPt.h)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
SynchronizationOperatorSynOperator)是GeomativeStudio软件中的一个核心组件,负责协调多个设备或模块之间的同步操作。该组件主要处理设备同步、数据同步和状态同步,确保测量过程的同步性。通过与同步对话框(opsyndlg)的交互,用户可以配置同步参数并接收状态反馈。本文档将深入探讨SynOperator的实现机制,包括其如何协调时间基准和操作序列,以及与OperMediumPt类结合进行介质点同步计算的算法逻辑。同时,文档还将提供同步失败、时钟漂移等常见问题的诊断方法和解决方案,并评估同步精度和网络延迟对同步性能的影响。
## 项目结构
GeomativeStudio项目的结构清晰地组织了各个功能模块。核心的同步功能主要位于`cpp/Operator`目录下的`SynOperator.cpp``SynOperator.h`文件中。同步对话框的实现则分布在`cpp/Views`目录下的`opsyndlg.cpp``opsyntddlg.cpp``opsynsptdlg.cpp`文件中。此外,设备管理和项目管理的相关逻辑分别在`cpp/Managers`目录下的`DevManager.cpp``ProManager.cpp`文件中实现。脚本管理器的功能则由`SptManager.cpp`文件提供。这些文件共同构成了SynchronizationOperator的技术基础。
```mermaid
graph TD
subgraph "核心组件"
SynOperator[SynOperator.cpp]
OperMediumPt[OperMediumPt.cpp]
end
subgraph "视图组件"
opsyndlg[opsyndlg.cpp]
opsyntddlg[opsyntddlg.cpp]
opsynsptdlg[opsynsptdlg.cpp]
end
subgraph "管理器"
DevManager[DevManager.cpp]
ProManager[ProManager.cpp]
SptManager[SptManager.cpp]
end
SynOperator --> opsyndlg
opsyndlg --> opsyntddlg
opsyndlg --> opsynsptdlg
SynOperator --> OperMediumPt
opsyndlg --> DevManager
opsyndlg --> ProManager
opsyntddlg --> ProManager
opsynsptdlg --> SptManager
```
**图表来源**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp)
- [opsyndlg.cpp](file://cpp/Views/opsyndlg.cpp)
- [opsyntddlg.cpp](file://cpp/Views/opsyntddlg.cpp)
- [opsynsptdlg.cpp](file://cpp/Views/opsynsptdlg.cpp)
- [OperMediumPt.cpp](file://cpp/Operator/OperMediumPt.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
**章节来源**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp)
- [opsyndlg.cpp](file://cpp/Views/opsyndlg.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
## 核心组件
SynchronizationOperator的核心功能包括设备同步、数据同步和状态同步。它通过调用`Syn()`方法启动同步过程,该方法创建并初始化同步对话框`COpSynDlg`,然后显示该对话框以供用户进行配置。`InitialSynDlg`方法用于初始化同步对话框,从设备管理器中获取已连接的设备列表,并将其添加到对话框的设备选择下拉列表中。整个同步过程依赖于与设备管理器、项目管理器和脚本管理器的紧密协作,确保所有相关数据和配置都能正确同步。
**章节来源**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp#L32-L55)
- [SynOperator.h](file://h/SynOperator.h#L17-L18)
## 架构概述
SynchronizationOperator的架构设计旨在实现高效且可靠的同步操作。其主要组件包括`CSynOperator`类,负责协调同步流程;`COpSynDlg`类,提供用户界面以配置同步参数;以及`COpSynTDDlg``COpSynSptDlg`类,分别处理测试数据和脚本的同步。这些组件通过事件驱动的方式进行通信,确保用户操作能够及时反映到同步过程中。此外,`CSynOperator`还利用`CStateProcessor``CHandleProcessor`来处理状态变化和句柄生成,进一步增强了系统的稳定性和可维护性。
```mermaid
classDiagram
class CSynOperator {
+Syn()
+InitialSynDlg(COpSynDlg* pOpSynDlg)
-_ConnectionPtr m_pConnection
-CStateProcessor m_stateProcessor
-CHandleProcessor m_handleProcessor
}
class COpSynDlg {
+OnInitDialog()
+OnSelchangeOpSynTab()
+OnSelchangeTdDesn()
-COpSynTDDlg m_opSynTDDlg
-COpSynSptDlg m_opSynSptDlg
-CDevice* m_pDev
-_ConnectionPtr m_pConnection
}
class COpSynTDDlg {
+OnInitDialog()
+OnSelchangedTreeSynDms()
+OnItemchangedListSynTd()
+OnTdSel()
+OnTdRemove()
+OnCreate()
+OnDmsDel()
+OnTdDel()
+OnTdUpload()
-CListCtrl m_tdList
-CListCtrl m_selTdList
-CTreeCtrl m_dmsTree
-CDevice* m_pDev
}
class COpSynSptDlg {
+OnInitDialog()
+OnSptDownload()
+OnSptUpload()
+OnSptDel()
-CListCtrl m_locSptList
-CListCtrl m_hostSptList
-CDevice* m_pDev
-int m_iSelSCID
}
CSynOperator --> COpSynDlg : "创建并初始化"
COpSynDlg --> COpSynTDDlg : "包含"
COpSynDlg --> COpSynSptDlg : "包含"
COpSynTDDlg --> ProManager : "调用"
COpSynSptDlg --> SptManager : "调用"
```
**图表来源**
- [SynOperator.h](file://h/SynOperator.h#L13-L24)
- [opsyndlg.h](file://h/opsyndlg.h#L19-L62)
- [opsyntddlg.h](file://h/opsyntddlg.h#L15-L61)
- [opsynsptdlg.h](file://h/opsynsptdlg.h#L13-L58)
## 详细组件分析
### SynOperator分析
`CSynOperator`类是同步操作的核心,其主要职责是启动和管理同步流程。`Syn()`方法通过创建`COpSynDlg`实例并调用其`RunModalLoop`方法来启动非模态窗口的模态循环,从而允许用户在不阻塞主程序的情况下进行同步配置。`InitialSynDlg`方法负责初始化同步对话框,从设备管理器中获取当前连接的设备列表,并将这些设备的信息填充到对话框的设备选择下拉列表中。这一过程确保了用户能够看到所有可用的设备,并选择需要同步的目标设备。
#### 对象导向组件:
```mermaid
classDiagram
class CSynOperator {
+Syn()
+InitialSynDlg(COpSynDlg* pOpSynDlg)
-_ConnectionPtr m_pConnection
-CStateProcessor m_stateProcessor
-CHandleProcessor m_handleProcessor
}
class COpSynDlg {
+OnInitDialog()
+OnSelchangeOpSynTab()
+OnSelchangeTdDesn()
-COpSynTDDlg m_opSynTDDlg
-COpSynSptDlg m_opSynSptDlg
-CDevice* m_pDev
-_ConnectionPtr m_pConnection
}
CSynOperator --> COpSynDlg : "创建并初始化"
```
**图表来源**
- [SynOperator.h](file://h/SynOperator.h#L13-L24)
- [opsyndlg.h](file://h/opsyndlg.h#L19-L62)
**章节来源**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp#L21-L55)
- [SynOperator.h](file://h/SynOperator.h#L13-L24)
### OperMediumPt分析
`COperMediumPt`类负责处理介质点的同步计算,特别是在不同类型的测量装置中进行深度排序。`InitiSortInfo`方法根据指定的方法初始化排序信息,而`AddSortPtInfo`方法则用于添加具体的排序点信息。`GetUniSptXPos`方法计算统一测点的位置,这是通过分析四个电极的位置(A、B、M、N)来完成的。对于不同类型的装置(如四级、三级、二级装置),该方法采用不同的算法来计算测点位置,确保结果的准确性。`GetFirstSortID``GetNextSortID`方法则用于遍历排序后的测点列表,提供有序的访问接口。
#### 对象导向组件:
```mermaid
classDiagram
class COperMediumPt {
+COperMediumPt(int iAR)
+~COperMediumPt()
+InitiSortInfo(int iMethod)
+AddSortPtInfo(int iA, int iB, int iM, int iN, int iLayer, int iIndex)
+GetUniSptXPos(int iA, int iB, int iM, int iN)
+GetFirstSortID(int iMethod)
+GetNextSortID()
-int m_iAR
-std : : map<STDepthSortKey, int> m_mapDepthSort
-std : : map<STDepthSortKey, int> : : iterator m_iterSortDepth
}
class STDepthSortKey {
+float fXPos
+int iLayer
+operator < (const STDepthSortKey& Obj) const
}
COperMediumPt --> STDepthSortKey : "使用"
```
**图表来源**
- [OperMediumPt.h](file://h/OperMediumPt.h#L39-L58)
- [OperMediumPt.cpp](file://cpp/Operator/OperMediumPt.cpp#L18-L137)
**章节来源**
- [OperMediumPt.cpp](file://cpp/Operator/OperMediumPt.cpp#L18-L137)
- [OperMediumPt.h](file://h/OperMediumPt.h#L39-L58)
### 同步对话框交互流程
同步对话框(`COpSynDlg`)提供了用户与SynchronizationOperator交互的界面。当用户选择同步操作时,`CSynOperator`会创建`COpSynDlg`实例并显示它。`OnInitDialog`方法初始化对话框,设置标签文本和控件布局。`OnSelchangeOpSynTab`方法处理标签页切换事件,根据用户选择的不同标签页(测试数据或脚本)显示相应的子对话框。`OnSelchangeTdDesn`方法在用户选择不同的设备时更新测试数据和脚本列表,确保用户能够看到与所选设备相关的所有信息。
#### API/服务组件:
```mermaid
sequenceDiagram
participant User as "用户"
participant SynOperator as "CSynOperator"
participant OpSynDlg as "COpSynDlg"
participant OpSynTDDlg as "COpSynTDDlg"
participant OpSynSptDlg as "COpSynSptDlg"
participant ProManager as "CProManager"
participant SptManager as "CSptManager"
User->>SynOperator : 调用Syn()
SynOperator->>OpSynDlg : 创建并初始化
OpSynDlg->>OpSynDlg : OnInitDialog()
OpSynDlg->>OpSynTDDlg : 显示
OpSynDlg->>OpSynSptDlg : 隐藏
User->>OpSynDlg : 切换标签页
OpSynDlg->>OpSynDlg : OnSelchangeOpSynTab()
OpSynDlg->>OpSynTDDlg : 隐藏
OpSynDlg->>OpSynSptDlg : 显示
User->>OpSynDlg : 选择设备
OpSynDlg->>OpSynDlg : OnSelchangeTdDesn()
OpSynDlg->>ProManager : 获取测试数据
ProManager-->>OpSynDlg : 返回测试数据
OpSynDlg->>SptManager : 获取脚本
SptManager-->>OpSynDlg : 返回脚本
```
**图表来源**
- [opsyndlg.cpp](file://cpp/Views/opsyndlg.cpp#L30-L237)
- [opsyntddlg.cpp](file://cpp/Views/opsyntddlg.cpp#L43-L200)
- [opsynsptdlg.cpp](file://cpp/Views/opsynsptdlg.cpp#L38-L200)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L53-L93)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L30-L53)
**章节来源**
- [opsyndlg.cpp](file://cpp/Views/opsyndlg.cpp#L30-L237)
- [opsyntddlg.cpp](file://cpp/Views/opsyntddlg.cpp#L43-L200)
- [opsynsptdlg.cpp](file://cpp/Views/opsynsptdlg.cpp#L38-L200)
## 依赖分析
SynchronizationOperator的实现依赖于多个关键组件,包括设备管理器(`CDevManager`)、项目管理器(`CProManager`)和脚本管理器(`CSptManager`)。`CDevManager`负责管理所有连接的设备,提供设备列表和状态信息。`CProManager`管理项目和测试区域的数据,确保同步过程中能够正确识别和处理相关的测试数据。`CSptManager`则负责脚本的创建、删除和同步,确保设备上的脚本与本地数据库保持一致。这些组件之间的依赖关系通过接口调用和数据传递来实现,形成了一个紧密协作的系统。
```mermaid
graph TD
SynOperator[CSynOperator] --> OpSynDlg[COpSynDlg]
OpSynDlg --> OpSynTDDlg[COpSynTDDlg]
OpSynDlg --> OpSynSptDlg[COpSynSptDlg]
OpSynTDDlg --> ProManager[CProManager]
OpSynSptDlg --> SptManager[CSptManager]
OpSynDlg --> DevManager[CDevManager]
ProManager --> Database[(数据库)]
SptManager --> Database
DevManager --> Database
```
**图表来源**
- [SynOperator.h](file://h/SynOperator.h#L13-L24)
- [opsyndlg.h](file://h/opsyndlg.h#L19-L62)
- [opsyntddlg.h](file://h/opsyntddlg.h#L15-L61)
- [opsynsptdlg.h](file://h/opsynsptdlg.h#L13-L58)
- [DevManager.h](file://h/DevManager.h#L22-L54)
- [ProManager.h](file://h/ProManager.h#L32-L64)
- [SptManager.h](file://h/SptManager.h#L27-L85)
**章节来源**
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L24-L46)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L32-L51)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L74-L83)
## 性能考虑
SynchronizationOperator在设计时充分考虑了性能因素。首先,通过使用非模态窗口的模态循环,避免了阻塞主程序的执行,提高了用户体验。其次,同步过程中采用了批量操作,减少了与数据库和设备的交互次数,从而降低了网络延迟的影响。此外,`COperMediumPt`类中的算法优化确保了介质点位置计算的高效性,即使在处理大量数据时也能保持良好的性能表现。为了进一步优化同步稳定性,建议在高网络延迟环境下使用更长的超时设置,并定期检查设备状态以确保同步过程的顺利进行。
## 故障排除指南
在使用SynchronizationOperator时,可能会遇到同步失败或时钟漂移等问题。对于同步失败,首先应检查设备连接状态和网络状况,确保设备能够正常通信。如果问题仍然存在,可以尝试重新启动设备或软件,有时这能解决临时的通信故障。对于时钟漂移问题,建议定期校准设备时钟,并在同步配置中启用时钟同步功能。此外,查看日志文件可以帮助定位具体的问题原因,例如通过分析`Device.cpp`中的日志输出,可以了解同步过程中具体的错误信息。
**章节来源**
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L1779-L1908)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L595-L637)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2696-L2739)
## 结论
SynchronizationOperator是GeomativeStudio软件中实现设备、数据和状态同步的关键组件。通过深入分析其架构和实现机制,我们可以看到它如何有效地协调多个设备或模块的时间基准和操作序列,确保测量过程的同步性。结合`OperMediumPt`类的介质点同步计算算法,SynchronizationOperator不仅提供了强大的同步功能,还保证了计算的准确性和效率。通过与同步对话框的交互,用户可以方便地配置同步参数并监控同步状态。针对常见的同步问题,文档提供了详细的诊断方法和解决方案,帮助用户快速解决问题。总体而言,SynchronizationOperator的设计充分考虑了性能和稳定性,为用户提供了一个可靠且高效的同步解决方案。