LAPTOP-SNT8I5JK\Boounion
2025-09-13 49c116b0a9d6ad26dae0d5ec915ea6f7fe5684f4
Merge branch 'liuyang'
已添加2个文件
已修改19个文件
254 ■■■■ 文件已修改
SourceCode/Bond/SGMeasurement/CCLinkPerformance/CCLinkIEControl.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/CCLinkPerformance/CCLinkIEControl.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/CCLinkPerformance/PerformanceMelsec.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/CCLinkPerformance/PerformanceMelsec.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/Logger.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/Logger.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/PLCSignalListener.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/ProductResultStorage.cpp 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/ProductResultStorage.h 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.cpp 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.h 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.filters 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/framework.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/pch.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/pch.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/resource.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/targetver.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/CCLinkPerformance/CCLinkIEControl.cpp
@@ -1,4 +1,4 @@
#include "pch.h"
#include "pch.h"
#include "CCLinkIEControl.h"
CCCLinkIEControl::CCCLinkIEControl() : CPerformanceMelsec(BoardType::CC_LINK_IE_CONTROL) {}
SourceCode/Bond/SGMeasurement/CCLinkPerformance/CCLinkIEControl.h
@@ -1,4 +1,4 @@
#ifndef CCLINKIECONTROL_H
#ifndef CCLINKIECONTROL_H
#define CCLINKIECONTROL_H
#include "PerformanceMelsec.h"
SourceCode/Bond/SGMeasurement/CCLinkPerformance/PerformanceMelsec.cpp
@@ -1,4 +1,4 @@
// PerformanceMelsec.cpp: implementation of the CPerformanceMelsec class.
// PerformanceMelsec.cpp: implementation of the CPerformanceMelsec class.
//
//////////////////////////////////////////////////////////////////////
#include "pch.h"
SourceCode/Bond/SGMeasurement/CCLinkPerformance/PerformanceMelsec.h
@@ -1,4 +1,4 @@
#ifndef PERFORMANCE_MELSEC_H
#ifndef PERFORMANCE_MELSEC_H
#define PERFORMANCE_MELSEC_H
#include "Mdfunc.h"
SourceCode/Bond/SGMeasurement/Logger.cpp
@@ -1,4 +1,4 @@
#include "pch.h"
#include "pch.h"
#include "Logger.h"
CLogger& CLogger::Instance()
SourceCode/Bond/SGMeasurement/Logger.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <afx.h>
class CLogger
SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp
@@ -1,4 +1,4 @@
#include "pch.h"
#include "pch.h"
#include "PLCSignalListener.h"
// === æ—¥å¿—打印类型 ===
@@ -247,13 +247,10 @@
                // ä¸Šå‡æ²¿è§¦å‘
                switch (i) {
                case 0:
                    // Start å‘½ä»¤
                    if (m_cbStart) {
                        m_cbStart();
                        WriteOutValues(OutValuesArray{ 0.0, 0.0, 0.0, 0.0 });
                        if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) {
                            m_vecAckSent[i] = true;
                            m_vecAckCounter[i] = 0;
                        }
                        std::string strProductID;
                        if (ReadProductID(strProductID)) {
@@ -262,21 +259,31 @@
                            LOG_MSG(msg, LOG_TYPE_SUCCESS);
                        }
                    }
                    break;
                case 1:
                    if (m_cbStop) {
                        m_cbStop();
                    // å‘送应答信号
                        if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) {
                            m_vecAckSent[i] = true;
                            m_vecAckCounter[i] = 0;
                        }
                    break;
                case 1:
                    // Stop å‘½ä»¤
                    if (m_cbStop) {
                        m_cbStop();
                    }
                    // Analyze å‘½ä»¤
                    if (m_cbAnalyze) {
                        auto results = m_cbAnalyze();
                        WriteOutValues(results);
                    }
                    // å‘送应答信号
                    if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) {
                        m_vecAckSent[i] = true;
                        m_vecAckCounter[i] = 0;
                    }
                    break;
                }
            }
SourceCode/Bond/SGMeasurement/PLCSignalListener.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CCLinkIEControl.h"
SourceCode/Bond/SGMeasurement/ProductResultStorage.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
#include "pch.h"
#include "ProductResultStorage.h"
CProductResultStorage::CProductResultStorage()
{
    TCHAR szPath[MAX_PATH] = { 0 };
    GetModuleFileName(NULL, szPath, MAX_PATH);
    CString strExePath(szPath);
    int pos = strExePath.ReverseFind(_T('\\'));
    if (pos != -1) {
        m_strBaseResultDir = strExePath.Left(pos) + _T("\\Data");
    }
    else {
        m_strBaseResultDir = _T(".\\Data");
    }
}
void CProductResultStorage::SaveAnalyzeResult(const CString& strProductID, const std::array<double, 4>& result)
{
    CString strFilePath = MakeResultCsvPath(_T("MeasurementResults"));
    CString strHeader = _T("Timestamp,ProductID,OUT1,OUT2,OUT3,OUT4\r\n");
    // æ—¶é—´æˆ³
    CTime now = CTime::GetCurrentTime();
    CString strTimestamp;
    strTimestamp.Format(_T("%02d:%02d:%02d"), now.GetHour(), now.GetMinute(), now.GetSecond());
    // ç»“果行
    CString strBody;
    strBody.Format(_T("%s,%s,%.3f,%.3f,%.3f,%.3f\r\n"), strTimestamp, strProductID, result[0], result[1], result[2], result[3]);
    AppendCsvWithHeader(strFilePath, strHeader, strBody);
}
CString CProductResultStorage::MakeResultCsvPath(const CString& strFileName)
{
    SYSTEMTIME st;
    GetLocalTime(&st);
    CString strDate;
    strDate.Format(_T("%04d%02d%02d"), st.wYear, st.wMonth, st.wDay);
    if (GetFileAttributes(m_strBaseResultDir) == INVALID_FILE_ATTRIBUTES) {
        CreateDirectory(m_strBaseResultDir, NULL);
    }
    CString strFilePath;
    strFilePath.Format(_T("%s\\%s_%s.csv"), m_strBaseResultDir, strFileName, strDate);
    return strFilePath;
}
BOOL CProductResultStorage::AppendCsvWithHeader(const CString& strFilePath, const CString& strHeader, const CString& strBody)
{
    if (strBody.IsEmpty()) {
        return FALSE;
    }
    CFile f;
    CFileException ex;
    if (!f.Open(strFilePath, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate | CFile::shareDenyWrite | CFile::shareDenyRead, &ex)) {
        return FALSE;
    }
    if (f.SeekToEnd() == 0L) {
        f.Write(strHeader, strHeader.GetLength() * sizeof(TCHAR));
    }
    f.Write(strBody, strBody.GetLength() * sizeof(TCHAR));
    f.Close();
    return TRUE;
}
SourceCode/Bond/SGMeasurement/ProductResultStorage.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
#pragma once
#include <array>
class CProductResultStorage
{
public:
    CProductResultStorage();
    ~CProductResultStorage() = default;
    void SaveAnalyzeResult(const CString& strProductID, const std::array<double, 4>& result);
private:
    CString MakeResultCsvPath(const CString& strFileName);
    BOOL AppendCsvWithHeader(const CString& strFilePath, const CString& strHeader, const CString& strBody);
    CString m_strBaseResultDir;
};
SourceCode/Bond/SGMeasurement/SGMeasurement.cpp
@@ -1,4 +1,4 @@

// SGMeasurement.cpp: å®šä¹‰åº”用程序的类行为。
//
@@ -7,10 +7,61 @@
#include "SGMeasurement.h"
#include "SGMeasurementDlg.h"
#include <DbgHelp.h>
#pragma comment(lib, "DbgHelp.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* pExceptionInfo)
{
    // èŽ·å–å½“å‰ç¨‹åºç›®å½•
    TCHAR szAppPath[MAX_PATH] = { 0 };
    ::GetModuleFileName(NULL, szAppPath, MAX_PATH);
    PathRemoveFileSpec(szAppPath);
    // æž„造 Temp æ–‡ä»¶å¤¹è·¯å¾„
    CString strTempPath;
    strTempPath.Format(_T("%s\\Temp"), szAppPath);
    CreateDirectory(strTempPath, NULL);
    // ç”Ÿæˆå¸¦æ—¶é—´æˆ³çš„ Dump æ–‡ä»¶å
    SYSTEMTIME st;
    GetLocalTime(&st);
    CString strDumpFile;
    strDumpFile.Format(
        _T("%s\\SG_%04d%02d%02d_%02d%02d%02d.dmp"),
        strTempPath,
        st.wYear, st.wMonth, st.wDay,
        st.wHour, st.wMinute, st.wSecond
    );
    // æ‰“å¼€ dump æ–‡ä»¶
    HANDLE hFile = CreateFile(strDumpFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
        dumpInfo.ExceptionPointers = pExceptionInfo;
        dumpInfo.ThreadId = GetCurrentThreadId();
        dumpInfo.ClientPointers = TRUE;
        // å†™å®Œæ•´å†…å­˜ dump
        BOOL success = MiniDumpWriteDump(
            GetCurrentProcess(),
            GetCurrentProcessId(),
            hFile,
            MiniDumpWithFullMemory,
            &dumpInfo,
            NULL,
            NULL
        );
        CloseHandle(hFile);
    }
    return EXCEPTION_EXECUTE_HANDLER;
}
// CSGMeasurementApp
@@ -51,6 +102,18 @@
    CWinApp::InitInstance();
    // å”¯ä¸€å®žä¾‹è¿è¡Œæ£€æµ‹
    m_hMutex = ::CreateMutex(NULL, FALSE, _T("MutexEdgeInspector_App"));
    if (m_hMutex != NULL) {
        if (::GetLastError() == ERROR_ALREADY_EXISTS) {
            AfxMessageBox(_T("The Program is already running. Exit this Program."), MB_OK | MB_ICONERROR);
            return FALSE;
        }
    }
    // è®¾ç½®æœªå¤„理异常过滤器,捕获崩溃并生成 Dump æ–‡ä»¶
    SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
    // åˆå§‹åŒ– MFC RichEdit æŽ§ä»¶
    AfxInitRichEdit2();
@@ -75,23 +138,19 @@
    CSGMeasurementDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
    if (nResponse == IDOK) {
        // TODO:“确定”来关闭对话框的代码
    }
    else if (nResponse == IDCANCEL)
    {
    else if (nResponse == IDCANCEL) {
        // TODO:“取消”来关闭对话框的代码 
    }
    else if (nResponse == -1)
    {
    else if (nResponse == -1) {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != nullptr)
    {
    if (pShellManager != nullptr) {
        delete pShellManager;
    }
@@ -102,3 +161,12 @@
    // ç”±äºŽå¯¹è¯æ¡†å·²å…³é—­ï¼Œæ‰€ä»¥å°†è¿”回 FALSE ä»¥ä¾¿é€€å‡ºåº”用程序,而不是启动应用程序的消息泵。
    return FALSE;
}
int CSGMeasurementApp::ExitInstance()
{
    if (m_hMutex) {
        CloseHandle(m_hMutex);
        m_hMutex = nullptr;
    }
    return CWinApp::ExitInstance();
}
SourceCode/Bond/SGMeasurement/SGMeasurement.h
@@ -1,4 +1,4 @@

// SGMeasurement.h: PROJECT_NAME åº”用程序的主头文件
//
@@ -23,10 +23,13 @@
// é‡å†™
public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
// å®žçް
    DECLARE_MESSAGE_MAP()
private:
    HANDLE m_hMutex;
};
extern CSGMeasurementApp theApp;
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj
@@ -209,6 +209,7 @@
    <ClInclude Include="Logger.h" />
    <ClInclude Include="pch.h" />
    <ClInclude Include="PLCSignalListener.h" />
    <ClInclude Include="ProductResultStorage.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SGMeasurement.h" />
    <ClInclude Include="SGMeasurementDlg.h" />
@@ -225,6 +226,7 @@
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="PLCSignalListener.cpp" />
    <ClCompile Include="ProductResultStorage.cpp" />
    <ClCompile Include="SGMeasurement.cpp" />
    <ClCompile Include="SGMeasurementDlg.cpp" />
  </ItemGroup>
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.filters
@@ -48,6 +48,9 @@
    <ClInclude Include="PLCSignalListener.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="ProductResultStorage.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="SGMeasurement.cpp">
@@ -71,6 +74,9 @@
    <ClCompile Include="PLCSignalListener.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="ProductResultStorage.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="SGMeasurement.rc">
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -1,4 +1,4 @@

// SGMeasurementDlg.cpp: å®žçŽ°æ–‡ä»¶
//
@@ -932,6 +932,10 @@
            result[i] = AnalyzeStoredData(i + 1); // OUT1 ~ OUT4
        }
        std::string strProductID;
        m_plcListener.ReadProductID(strProductID);
        m_resultStorage.SaveAnalyzeResult(CString(strProductID.c_str()), result);
        CString strLog;
        strLog.Format(_T("分析结果:OUT1: %.3f, OUT2: %.3f, OUT3: %.3f, OUT4: %.3f"), result[0], result[1], result[2], result[3]);
        return result;
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h
@@ -1,10 +1,11 @@

// SGMeasurementDlg.h: å¤´æ–‡ä»¶
//
#pragma once
#include "PLCSignalListener.h"
#include "ProductResultStorage.h"
#include <map>
#include <vector>
@@ -340,4 +341,11 @@
     * @brief PLC ä¿¡å·ç›‘听器实例,用于处理 PLC ä¿¡å·äº‹ä»¶
     */
    CPLCSignalListener m_plcListener;
    // === äº§å“ç»“果存储 ===
    /**
     * @brief äº§å“ç»“果存储实例,用于保存和管理测量结果
     */
    CProductResultStorage m_resultStorage;
};
SourceCode/Bond/SGMeasurement/framework.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // ä»Ž Windows å¤´ä¸­æŽ’除极少使用的资料
SourceCode/Bond/SGMeasurement/pch.cpp
@@ -1,4 +1,4 @@
// pch.cpp: ä¸Žé¢„编译标头对应的源文件
// pch.cpp: ä¸Žé¢„编译标头对应的源文件
#include "pch.h"
SourceCode/Bond/SGMeasurement/pch.h
@@ -1,4 +1,4 @@
// pch.h: è¿™æ˜¯é¢„编译标头文件。
// pch.h: è¿™æ˜¯é¢„编译标头文件。
// ä¸‹æ–¹åˆ—出的文件仅编译一次,提高了将来生成的生成性能。
// è¿™è¿˜å°†å½±å“ IntelliSense æ€§èƒ½ï¼ŒåŒ…括代码完成和许多代码浏览功能。
// ä½†æ˜¯ï¼Œå¦‚果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
SourceCode/Bond/SGMeasurement/resource.h
@@ -1,4 +1,4 @@
//{{NO_DEPENDENCIES}}
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ ç”Ÿæˆçš„包含文件。
// ä¾› SGMeasurement.rc ä½¿ç”¨
//
SourceCode/Bond/SGMeasurement/targetver.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚