已添加4个文件
已修改15个文件
770 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CPageReport.cpp 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageReport.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageVarialbles.cpp 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReport.cpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReport.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReportEditDlg.cpp 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReportEditDlg.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CUserManager2.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVariable.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVariableEditDlg2.cpp 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVariableEditDlg2.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 238 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/ReportList.txt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/VariableList.txt 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageReport.cpp
@@ -5,6 +5,8 @@
#include "Servo.h"
#include "CPageReport.h"
#include "afxdialogex.h"
#include "CReportEditDlg.h"
#include <algorithm>
// CPageReport å¯¹è¯æ¡†
@@ -32,6 +34,7 @@
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CPageReport::OnLvnItemchangedList1)
END_MESSAGE_MAP()
@@ -123,3 +126,112 @@
        m_listCtrl.SetItemText(index, 2, item->getVariablesIdsText().c_str());
    }
}
void CPageReport::OnCreateBtns()
{
    const int BTN_W = 80;
    const int BTN_H = 28;
    CreateBtn(_T("新增"), BTN_W, BTN_H, 2001);
    CreateBtn(_T("删除"), BTN_W, BTN_H, 2002)->EnableWindow(FALSE);
    CreateBtn(_T("编辑"), BTN_W, BTN_H, 2003)->EnableWindow(FALSE);
}
void CPageReport::OnLvnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    int nSelCount = m_listCtrl.GetSelectedCount();
    if (CButton* pDel = GetBtnByName("删除")) {
        pDel->EnableWindow(nSelCount > 0);
    }
    if (CButton* pEdit = GetBtnByName("编辑")) {
        pEdit->EnableWindow(nSelCount > 0);
    }
    *pResult = 0;
}
void CPageReport::OnClickedBtn(const char* btnName)
{
    ASSERT(btnName);
    if (_strcmpi(btnName, "新增") == 0) {
        int rc = UX_CanExecute(L"addReports");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        unsigned int newId = theApp.m_model.m_hsmsPassive.getMaxReportId() + 1;
        std::vector<unsigned int> initVids;
        CReportEditDlg dlg(_T("新增报告"), static_cast<int>(newId), initVids, this);
        if (dlg.DoModal() != IDOK) return;
        const auto& vids = dlg.GetSelectedVids();
        int ret = theApp.m_model.m_hsmsPassive.addReport(static_cast<int>(newId), vids);
        if (ret == 0) {
            UX_RecordAction(L"addReports");
            m_listCtrl.DeleteAllItems();
            loadReports();
            if (CButton* pDel = GetBtnByName("删除")) pDel->EnableWindow(FALSE);
            if (CButton* pEdit = GetBtnByName("编辑")) pEdit->EnableWindow(FALSE);
        }
        else {
            AfxMessageBox(_T("新增报告失败(可能ID重复或文件写入失败)"));
        }
    }
    else if (_strcmpi(btnName, "删除") == 0) {
        POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
        if (pos == nullptr) return;
        int nItem = m_listCtrl.GetNextSelectedItem(pos);
        auto pRpt = reinterpret_cast<SERVO::CReport*>(m_listCtrl.GetItemData(nItem));
        if (pRpt == nullptr) return;
        int rc = UX_CanExecute(L"delReports");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        int ret = theApp.m_model.m_hsmsPassive.deleteReport((int)pRpt->getReportId());
        if (ret == 0) {
            UX_RecordAction(L"delReports");
            m_listCtrl.DeleteAllItems();
            loadReports();
            if (CButton* pDel = GetBtnByName("删除")) pDel->EnableWindow(FALSE);
            if (CButton* pEdit = GetBtnByName("编辑")) pEdit->EnableWindow(FALSE);
        }
        else {
            AfxMessageBox(_T("删除报告失败"));
        }
    }
    else if (_strcmpi(btnName, "编辑") == 0) {
        POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
        if (pos == nullptr) return;
        int nItem = m_listCtrl.GetNextSelectedItem(pos);
        auto pRpt = reinterpret_cast<SERVO::CReport*>(m_listCtrl.GetItemData(nItem));
        if (pRpt == nullptr) return;
        int rc = UX_CanExecute(L"editReports");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        std::vector<unsigned int> vidsExisting = pRpt->getVids();
        CReportEditDlg dlg(_T("编辑报告"), (int)pRpt->getReportId(), vidsExisting, this);
        if (dlg.DoModal() != IDOK) return;
        const auto& vids = dlg.GetSelectedVids();
        int ret = theApp.m_model.m_hsmsPassive.updateReport((int)pRpt->getReportId(), vids);
        if (ret == 0) {
            UX_RecordAction(L"editReports");
            m_listCtrl.DeleteAllItems();
            loadReports();
            if (CButton* pDel = GetBtnByName("删除")) pDel->EnableWindow(FALSE);
            if (CButton* pEdit = GetBtnByName("编辑")) pEdit->EnableWindow(FALSE);
        }
        else {
            AfxMessageBox(_T("编辑报告失败(可能文件写入失败)"));
        }
    }
}
SourceCode/Bond/Servo/CPageReport.h
@@ -16,6 +16,8 @@
private:
    CListCtrlEx m_listCtrl;
    void OnCreateBtns() override;
    void OnClickedBtn(const char* btnName) override;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
@@ -31,4 +33,5 @@
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnLvnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult);
};
SourceCode/Bond/Servo/CPageVarialbles.cpp
@@ -5,6 +5,7 @@
#include "Servo.h"
#include "CPageVarialbles.h"
#include "afxdialogex.h"
#include "CVariableEditDlg2.h"
// CPageVarialbles å¯¹è¯æ¡†
@@ -161,7 +162,28 @@
{
    ASSERT(btnName);
    if (_strcmpi(btnName, "新增") == 0) {
        // TODO: æ–°å¢žé€»è¾‘
        int rc = UX_CanExecute(L"addVarialbles");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        unsigned int newId = theApp.m_model.m_hsmsPassive.getMaxVariableId();
        int newIdInt = static_cast<int>(newId + 1);
        CVariableEditDlg2 dlg(_T("新增变量"), newIdInt, _T("U1"), _T(""), _T(""), this);
        if (dlg.DoModal() != IDOK) return;
        CString name = dlg.GetNameText();
        CString fmt = dlg.GetTypeText();
        CString remark = dlg.GetRemark();
        int ret = theApp.m_model.m_hsmsPassive.addVariable(CT2A(name), CT2A(fmt), CT2A(remark), newIdInt);
        if (ret == 0) {
            UX_RecordAction(L"addVarialbles");
            m_listCtrl.DeleteAllItems();
            loadVariables();
        }
        else {
            AfxMessageBox(_T("新增变量失败,格式是否正确?(U1/U2/I2/A20/A50/L)"));
        }
    }
    else if (_strcmpi(btnName, "删除") == 0) {
        POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
@@ -170,8 +192,15 @@
        auto pVar = reinterpret_cast<SERVO::CVariable*>(m_listCtrl.GetItemData(nItem));
        if (pVar == nullptr) return;
        int rc = UX_CanExecute(L"delVarialbles");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        int ret = theApp.m_model.m_hsmsPassive.deleteVariable(pVar->getVarialbleId());
        if (ret == 0) {
            UX_RecordAction(L"delVarialbles");
            m_listCtrl.DeleteAllItems();
            loadVariables();
            if (CButton* pDel = GetBtnByName("删除")) pDel->EnableWindow(FALSE);
@@ -179,6 +208,36 @@
        }
    }
    else if (_strcmpi(btnName, "编辑") == 0) {
        // TODO: ç¼–辑逻辑
        POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
        if (pos == nullptr) return;
        int nItem = m_listCtrl.GetNextSelectedItem(pos);
        auto pVar = reinterpret_cast<SERVO::CVariable*>(m_listCtrl.GetItemData(nItem));
        if (pVar == nullptr) return;
        int rc = UX_CanExecute(L"editVarialbles");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return;
        }
        CVariableEditDlg2 dlg(_T("编辑变量"),
            pVar->getVarialbleId(),
            CString(CA2T(SERVO::CVariable::formatToString(pVar->getFormat()).c_str())),
            CString(CA2T(pVar->getName().c_str())),
            CString(CA2T(pVar->getRemark().c_str())),
            this);
        if (dlg.DoModal() != IDOK) return;
        CString name = dlg.GetNameText();
        CString fmt = dlg.GetTypeText();
        CString remark = dlg.GetRemark();
        int ret = theApp.m_model.m_hsmsPassive.updateVariable(pVar->getVarialbleId(), CT2A(name), CT2A(fmt), CT2A(remark));
        if (ret == 0) {
            UX_RecordAction(L"editVarialbles");
            m_listCtrl.DeleteAllItems();
            loadVariables();
        }
        else {
            AfxMessageBox(_T("编辑变量失败,格式是否正确?(U1/U2/I2/A20/A50/L)"));
        }
    }
}
SourceCode/Bond/Servo/CReport.cpp
@@ -8,12 +8,10 @@
        m_nReportId = 0;
    }
    CReport::CReport(unsigned int reportId, std::vector<unsigned int>& vids)
    CReport::CReport(unsigned int reportId, const std::vector<unsigned int>& vids)
    {
        m_nReportId = reportId;
        for (auto vid : vids) {
            m_vids.push_back(vid);
        }
        m_vids = vids;
    }
    CReport::~CReport()
SourceCode/Bond/Servo/CReport.h
@@ -7,7 +7,7 @@
    {
    public:
        CReport();
        CReport(unsigned int reportId, std::vector<unsigned int>& vids);
        CReport(unsigned int reportId, const std::vector<unsigned int>& vids);
        virtual ~CReport();
    public:
@@ -18,6 +18,7 @@
        std::vector<CVariable*>& getVariables();
        std::string getVariablesIdsText();
        bool getVariableName(unsigned int vid, std::string& strName);
        const std::vector<unsigned int>& getVids() const { return m_vids; }
    private:
        unsigned int m_nReportId;
SourceCode/Bond/Servo/CReportEditDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
#include "stdafx.h"
#include "CReportEditDlg.h"
#include "Servo.h"
#include "resource.h"
#include <algorithm>
IMPLEMENT_DYNAMIC(CReportEditDlg, CDialogEx)
CReportEditDlg::CReportEditDlg(const CString& title, int rptId, const std::vector<unsigned int>& vids, CWnd* pParent)
    : CDialogEx(IDD_DIALOG_REPORT_EDIT, pParent)
    , m_strTitle(title)
    , m_rptId(rptId)
    , m_vids(vids)
{
}
CReportEditDlg::~CReportEditDlg()
{
}
void CReportEditDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_RPT_ID, m_editId);
    DDX_Control(pDX, IDC_LIST_RPT_VARS, m_listVars);
}
BEGIN_MESSAGE_MAP(CReportEditDlg, CDialogEx)
END_MESSAGE_MAP()
BOOL CReportEditDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    SetWindowText(m_strTitle);
    CString strId;
    strId.Format(_T("%d"), m_rptId);
    m_editId.SetWindowText(strId);
    m_editId.SetReadOnly(TRUE);
    // åˆå§‹åŒ–列表
    m_listVars.SetExtendedStyle(m_listVars.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_CHECKBOXES);
    m_listVars.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 60);
    m_listVars.InsertColumn(1, _T("名称"), LVCFMT_LEFT, 140);
    m_listVars.InsertColumn(2, _T("格式"), LVCFMT_LEFT, 80);
    auto& vars = theApp.m_model.m_hsmsPassive.getVariables();
    for (int i = 0; i < (int)vars.size(); ++i) {
        auto v = vars[i];
        if (v == nullptr) continue;
        int idx = m_listVars.InsertItem(m_listVars.GetItemCount(), std::to_string(v->getVarialbleId()).c_str());
        m_listVars.SetItemText(idx, 1, v->getName().c_str());
        m_listVars.SetItemText(idx, 2, SERVO::CVariable::formatToString(v->getFormat()).c_str());
        m_listVars.SetItemData(idx, (DWORD_PTR)v->getVarialbleId());
        if (std::find(m_vids.begin(), m_vids.end(), v->getVarialbleId()) != m_vids.end()) {
            m_listVars.SetCheck(idx, TRUE);
        }
    }
    return TRUE;
}
void CReportEditDlg::OnOK()
{
    std::vector<unsigned int> selected;
    int count = m_listVars.GetItemCount();
    for (int i = 0; i < count; ++i) {
        if (m_listVars.GetCheck(i)) {
            selected.push_back((unsigned int)m_listVars.GetItemData(i));
        }
    }
    if (selected.empty()) {
        AfxMessageBox(_T("至少选择一个变量"));
        return;
    }
    m_vids.swap(selected);
    CDialogEx::OnOK();
}
SourceCode/Bond/Servo/CReportEditDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
#pragma once
#include "afxdialogex.h"
// æŠ¥å‘Šç¼–辑对话框(新增/编辑共用)
class CReportEditDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CReportEditDlg)
public:
    CReportEditDlg(const CString& title, int rptId, const std::vector<unsigned int>& vids, CWnd* pParent = nullptr);
    virtual ~CReportEditDlg();
    int GetReportId() const { return m_rptId; }
    const std::vector<unsigned int>& GetSelectedVids() const { return m_vids; }
protected:
    virtual BOOL OnInitDialog() override;
    virtual void DoDataExchange(CDataExchange* pDX) override;
    afx_msg void OnOK();
    DECLARE_MESSAGE_MAP()
private:
    CString m_strTitle;
    int m_rptId;
    std::vector<unsigned int> m_vids;
    CEdit m_editId;
    CListCtrl m_listVars;
};
SourceCode/Bond/Servo/CUserManager2.cpp
@@ -73,8 +73,21 @@
        UX_DefineAction(L"start", L"启动机台", L"Operator"); 
        UX_DefineAction(L"stop", L"停机", L"Operator");
        UX_DefineAction(L"recipe", L"编辑配方", L"Engineer");
        UX_DefineAction(L"recipe", L"编辑配方", L"PE");
        UX_DefineAction(L"delVarialbles", L"删除变量", L"PE");
        UX_DefineAction(L"addVarialbles", L"新增变量", L"PE");
        UX_DefineAction(L"editVarialbles", L"编辑变量", L"PE");
        UX_DefineAction(L"addReports", L"新增Report", L"PE");
        UX_DefineAction(L"editReports", L"编辑Report", L"PE");
        UX_DefineAction(L"delReports", L"删除Report", L"PE");
    }
    // ç¡®ä¿æƒé™å®šä¹‰å­˜åœ¨ï¼ˆå¹‚等)
    UX_DefineAction(L"addVarialbles", L"新增变量", L"PE");
    UX_DefineAction(L"editVarialbles", L"编辑变量", L"PE");
    UX_DefineAction(L"delVarialbles", L"删除变量", L"PE");
    UX_DefineAction(L"addReports", L"新增Report", L"PE");
    UX_DefineAction(L"editReports", L"编辑Report", L"PE");
    UX_DefineAction(L"delReports", L"删除Report", L"PE");
}
bool CUserManager2::login(const char* pszAccount, const char* pszPwd)
SourceCode/Bond/Servo/CVariable.h
@@ -3,7 +3,7 @@
namespace SERVO {
    // å˜é‡æ ¼å¼
    // å˜é‡ç±»åž‹
    enum class SVFromat {
        U1 = 0,
        U2,
@@ -33,6 +33,9 @@
        std::string getValue();
        __int64 getIntValue();
        std::vector<CVariable>& getVarsValue();
        void setName(const char* pszName) { m_strName = pszName; }
        void setFormat(const char* pszFmt) { m_format = toFormat(pszFmt); }
        void setRemark(const char* pszRemark) { m_strRemark = pszRemark; }
    private:
        unsigned int m_nVarialbeId;
SourceCode/Bond/Servo/CVariableEditDlg2.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
#include "stdafx.h"
#include "CVariableEditDlg2.h"
#include "resource.h"
IMPLEMENT_DYNAMIC(CVariableEditDlg2, CDialogEx)
CVariableEditDlg2::CVariableEditDlg2(const CString& title, int varId, const CString& type, const CString& name, const CString& remark, CWnd* pParent)
    : CDialogEx(IDD_DIALOG_VARIABLE_EDIT2, pParent),
    m_strTitle(title),
    m_varId(varId),
    m_strType(type),
    m_strName(name),
    m_strRemark(remark)
{
}
CVariableEditDlg2::~CVariableEditDlg2()
{
}
void CVariableEditDlg2::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_VAR_ID, m_editId);
    DDX_Control(pDX, IDC_COMBO_VAR_TYPE, m_cbType);
    DDX_Control(pDX, IDC_EDIT_VAR_NAME, m_editName);
    DDX_Control(pDX, IDC_EDIT_VAR_REMARK, m_editRemark);
}
BEGIN_MESSAGE_MAP(CVariableEditDlg2, CDialogEx)
END_MESSAGE_MAP()
BOOL CVariableEditDlg2::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    SetWindowText(m_strTitle);
    CString strId;
    strId.Format(_T("%d"), m_varId);
    m_editId.SetWindowText(strId);
    m_editId.SetReadOnly(TRUE);
    m_cbType.ResetContent();
    const TCHAR* fmts[] = { _T("U1"), _T("U2"), _T("I2"), _T("A20"), _T("A50"), _T("L") };
    for (auto f : fmts) {
        m_cbType.AddString(f);
    }
    if (!m_strType.IsEmpty()) {
        m_cbType.SelectString(-1, m_strType);
    }
    else {
        m_cbType.SetCurSel(0);
    }
    m_editName.SetWindowText(m_strName);
    m_editRemark.SetWindowText(m_strRemark);
    return TRUE;
}
void CVariableEditDlg2::OnOK()
{
    CString name, fmt, remark;
    m_editName.GetWindowText(name);
    m_cbType.GetWindowText(fmt);
    m_editRemark.GetWindowText(remark);
    fmt.MakeUpper();
    if (name.IsEmpty()) {
        AfxMessageBox(_T("名称不能为空"));
        return;
    }
    if (fmt.IsEmpty()) {
        AfxMessageBox(_T("类型不能为空"));
        return;
    }
    if (fmt != _T("U1") && fmt != _T("U2") && fmt != _T("I2")
        && fmt != _T("A20") && fmt != _T("A50") && fmt != _T("L")) {
        AfxMessageBox(_T("类型必须是 U1/U2/I2/A20/A50/L"));
        return;
    }
    m_strName = name;
    m_strType = fmt;
    m_strRemark = remark;
    CDialogEx::OnOK();
}
SourceCode/Bond/Servo/CVariableEditDlg2.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
#pragma once
#include "afxdialogex.h"
// å˜é‡ç¼–辑对话框(新增/编辑共用,使用资源模板)
class CVariableEditDlg2 : public CDialogEx
{
    DECLARE_DYNAMIC(CVariableEditDlg2)
public:
    CVariableEditDlg2(const CString& title, int varId, const CString& type, const CString& name, const CString& remark, CWnd* pParent = nullptr);
    virtual ~CVariableEditDlg2();
    int GetVarId() const { return m_varId; }
    CString GetTypeText() const { return m_strType; }
    CString GetNameText() const { return m_strName; }
    CString GetRemark() const { return m_strRemark; }
protected:
    virtual BOOL OnInitDialog() override;
    virtual void DoDataExchange(CDataExchange* pDX) override;
    afx_msg void OnOK();
    DECLARE_MESSAGE_MAP()
private:
    CString m_strTitle;
    int m_varId;
    CString m_strType;
    CString m_strName;
    CString m_strRemark;
    CEdit   m_editId, m_editName, m_editRemark;
    CComboBox m_cbType;
};
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -8,6 +8,8 @@
#include <time.h>  
#include <stdlib.h>  
#include <string.h>  
#include <algorithm>
#include <set>
#include <regex>
@@ -373,6 +375,17 @@
    return m_variabels;
}
unsigned int CHsmsPassive::getMaxVariableId() const
{
    unsigned int maxId = 0;
    for (auto item : m_variabels) {
        if (item && item->getVarialbleId() > maxId) {
            maxId = item->getVarialbleId();
        }
    }
    return maxId;
}
SERVO::CVariable* CHsmsPassive::getVariable(int variableId)
{
    for (auto item : m_variabels) {
@@ -453,7 +466,93 @@
    if (filepath.empty()) return -2;
    // å†™å›žæ–‡ä»¶ï¼Œä¿æŒåŽŸç¼–ç ï¼ˆUTF-8 æˆ–本地编码)
    return writeVariablesToFile(filepath);
}
void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(value);
    }
}
void CHsmsPassive::setVariableValue(const char* pszName, const char* value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(value);
    }
}
void CHsmsPassive::setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(vars);
    }
}
static bool isValidFormat(const std::string& fmt)
{
    static const std::set<std::string> allow = { "U1","U2","I2","A20","A50","L" };
    return allow.count(fmt) > 0;
}
int CHsmsPassive::addVariable(const char* pszName, const char* pszFormat, const char* pszRemark, int& outId)
{
    if (pszName == nullptr || pszFormat == nullptr) return -1;
    std::string fmt = pszFormat;
    std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
    if (!isValidFormat(fmt)) return -2;
    Lock();
    int maxId = 0;
    for (auto v : m_variabels) {
        if (v != nullptr && v->getVarialbleId() > maxId) {
            maxId = v->getVarialbleId();
        }
    }
    outId = maxId + 1;
    SERVO::CVariable* pNew = new SERVO::CVariable(std::to_string(outId).c_str(), pszName, fmt.c_str(), pszRemark ? pszRemark : "");
    m_variabels.push_back(pNew);
    auto filepath = m_strVariableFilepath;
    Unlock();
    if (filepath.empty()) return -3;
    return writeVariablesToFile(filepath);
}
int CHsmsPassive::updateVariable(int variableId, const char* pszName, const char* pszFormat, const char* pszRemark)
{
    if (pszName == nullptr || pszFormat == nullptr) return -1;
    std::string fmt = pszFormat;
    std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
    if (!isValidFormat(fmt)) return -2;
    Lock();
    auto it = std::find_if(m_variabels.begin(), m_variabels.end(), [=](SERVO::CVariable* v) {
        return v != nullptr && v->getVarialbleId() == variableId;
        });
    if (it == m_variabels.end()) {
        Unlock();
        return -4;
    }
    (*it)->setName(pszName);
    (*it)->setFormat(fmt.c_str());
    (*it)->setRemark(pszRemark ? pszRemark : "");
    auto filepath = m_strVariableFilepath;
    Unlock();
    if (filepath.empty()) return -3;
    return writeVariablesToFile(filepath);
}
int CHsmsPassive::writeVariablesToFile(const std::string& filepath)
{
    if (filepath.empty()) return -3;
    CFile file;
    if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
        return -3;
@@ -499,32 +598,11 @@
    return 0;
}
void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(value);
    }
}
void CHsmsPassive::setVariableValue(const char* pszName, const char* value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(value);
    }
}
void CHsmsPassive::setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
        v->setValue(vars);
    }
}
int CHsmsPassive::loadReports(const char* pszFilepath)
{
    m_strReportFilepath = pszFilepath;
    m_bReportUtf8 = false;
    m_bReportUtf8Bom = false;
    // å…¼å®¹ UTF-8/BOM ä¸Žæœ¬åœ°ç¼–码读取
    CFile file;
    if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
@@ -548,6 +626,8 @@
    // UTF-8 BOM
    if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
        offset = 3;
        m_bReportUtf8 = true;
        m_bReportUtf8Bom = true;
    }
    // UTF-16 LE BOM
@@ -577,6 +657,7 @@
            MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
                static_cast<int>(buffer.size() - off), temp.data(), need);
            content = temp.c_str();
            m_bReportUtf8 = true;
            return true;
        };
@@ -653,6 +734,17 @@
    return m_reports;
}
unsigned int CHsmsPassive::getMaxReportId() const
{
    unsigned int maxId = 0;
    for (auto item : m_reports) {
        if (item && item->getReportId() > maxId) {
            maxId = item->getReportId();
        }
    }
    return maxId;
}
SERVO::CReport* CHsmsPassive::getReport(int rptid)
{
    for (auto item : m_reports) {
@@ -677,6 +769,49 @@
    return false;
}
int CHsmsPassive::deleteReport(int rptid)
{
    if (!removeReport(rptid)) {
        return -1;
    }
    return writeReportsToFile(m_strReportFilepath);
}
int CHsmsPassive::addReport(int rptid, const std::vector<unsigned int>& vids)
{
    if (getReport(rptid) != nullptr) {
        return -1;
    }
    SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
    for (auto vid : vids) {
        SERVO::CVariable* pVariable = getVariable((int)vid);
        if (pVariable != nullptr) {
            pReport->addVariable(pVariable);
        }
    }
    m_reports.push_back(pReport);
    return writeReportsToFile(m_strReportFilepath);
}
int CHsmsPassive::updateReport(int rptid, const std::vector<unsigned int>& vids)
{
    for (auto iter = m_reports.begin(); iter != m_reports.end(); ++iter) {
        if ((*iter)->getReportId() == rptid) {
            delete (*iter);
            SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
            for (auto vid : vids) {
                SERVO::CVariable* pVariable = getVariable((int)vid);
                if (pVariable != nullptr) {
                    pReport->addVariable(pVariable);
                }
            }
            *iter = pReport;
            return writeReportsToFile(m_strReportFilepath);
        }
    }
    return -1;
}
void CHsmsPassive::clearAllReport()
{
    for (auto item : m_reports) {
@@ -685,6 +820,59 @@
    m_reports.clear();
}
int CHsmsPassive::writeReportsToFile(const std::string& filepath)
{
    if (filepath.empty()) return -1;
    CFile file;
    if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite)) {
        return -1;
    }
    if (m_bReportUtf8 && m_bReportUtf8Bom) {
        const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
        file.Write(bom, 3);
    }
    // header
    const std::string headerAnsi = "RPTID,(VID1,VID2,...)\r\n";
    if (m_bReportUtf8) {
        CStringA header = AnsiToUtf8(headerAnsi);
        file.Write(header.GetString(), header.GetLength());
    }
    else {
        file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
    }
    for (auto rpt : m_reports) {
        if (rpt == nullptr) continue;
        std::string line;
        line.reserve(64);
        line += std::to_string(rpt->getReportId());
        line += ",(";
        const auto& vids = rpt->getVids();
        for (size_t i = 0; i < vids.size(); ++i) {
            line += std::to_string(vids[i]);
            if (i + 1 < vids.size()) {
                line.push_back(',');
            }
        }
        line += ")\r\n";
        if (m_bReportUtf8) {
            CStringA out = AnsiToUtf8(line);
            file.Write(out.GetString(), out.GetLength());
        }
        else {
            file.Write(line.data(), (UINT)line.size());
        }
    }
    file.Close();
    return 0;
}
int CHsmsPassive::loadCollectionEvents(const char* pszFilepath)
{
    CFile file;
SourceCode/Bond/Servo/HsmsPassive.h
@@ -135,6 +135,9 @@
    // å–消 define report
    bool removeReport(int rptid);
    int deleteReport(int rptid);
    int addReport(int rptid, const std::vector<unsigned int>& vids);
    int updateReport(int rptid, const std::vector<unsigned int>& vids);
    void clearAllReport();
    // ä»Žæ–‡ä»¶ä¸­åŠ è½½CVariable列表
@@ -142,11 +145,14 @@
    // å–å¾—CVariable列表
    std::vector<SERVO::CVariable*>& getVariables();
    unsigned int getMaxVariableId() const;
    // å–得指定Variable
    SERVO::CVariable* getVariable(int variableId);
    SERVO::CVariable* getVariable(const char* pszName);
    int deleteVariable(int variableId);
    int addVariable(const char* pszName, const char* pszFormat, const char* pszRemark, int& outId);
    int updateVariable(int variableId, const char* pszName, const char* pszFormat, const char* pszRemark);
    // è®¾ç½®å˜é‡å€¼
    void setVariableValue(const char* pszName, __int64 value);
@@ -158,6 +164,7 @@
    // å–å¾—Report列表
    std::vector<SERVO::CReport*>& getReports();
    unsigned int getMaxReportId() const;
    // ä»Žæ–‡ä»¶ä¸­åŠ è½½CCollectionEvent列表
    int loadCollectionEvents(const char* pszFilepath);
@@ -235,6 +242,8 @@
    int onRecvMsg(IMessage* pMessage);
    void clearAllVariabel();
    std::vector<unsigned int> parseVidList(CString& strNums);
    int writeVariablesToFile(const std::string& filepath);
    int writeReportsToFile(const std::string& filepath);
private:
    CModel* m_pModel;
@@ -255,6 +264,9 @@
    std::string m_strVariableFilepath;
    bool m_bVariableUtf8{ false };
    bool m_bVariableUtf8Bom{ false };
    std::string m_strReportFilepath;
    bool m_bReportUtf8{ false };
    bool m_bReportUtf8Bom{ false };
    BOOL m_bCimWorking;
    HANDLE m_hCimWorkEvent;
    HANDLE m_hCimWorkThreadHandle;
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -248,6 +248,7 @@
    <ClInclude Include="CCjPage1.h" />
    <ClInclude Include="CProcessDataListDlg.h" />
    <ClInclude Include="CReport.h" />
    <ClInclude Include="CReportEditDlg.h" />
    <ClInclude Include="CRobotCmdContainerDlg.h" />
    <ClInclude Include="CRobotCmdTestDlg.h" />
    <ClInclude Include="CPagePortStatus.h" />
@@ -260,6 +261,7 @@
    <ClInclude Include="CUserEdit2Dlg.h" />
    <ClInclude Include="CUserXLogDlg.h" />
    <ClInclude Include="CVariable.h" />
    <ClInclude Include="CVariableEditDlg2.h" />
    <ClInclude Include="DeviceRecipeParamDlg.h" />
    <ClInclude Include="GlassJson.h" />
    <ClInclude Include="GlassLogDb.h" />
@@ -466,6 +468,7 @@
    <ClCompile Include="CCjPage1.cpp" />
    <ClCompile Include="CProcessDataListDlg.cpp" />
    <ClCompile Include="CReport.cpp" />
    <ClCompile Include="CReportEditDlg.cpp" />
    <ClCompile Include="CRobotCmdContainerDlg.cpp" />
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
    <ClCompile Include="CPagePortStatus.cpp" />
@@ -478,6 +481,7 @@
    <ClCompile Include="CUserEdit2Dlg.cpp" />
    <ClCompile Include="CUserXLogDlg.cpp" />
    <ClCompile Include="CVariable.cpp" />
    <ClCompile Include="CVariableEditDlg2.cpp" />
    <ClCompile Include="DeviceRecipeParamDlg.cpp" />
    <ClCompile Include="GlassJson.cpp" />
    <ClCompile Include="GlassLogDb.cpp" />
@@ -651,4 +655,4 @@
    <Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
    <Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
  </Target>
</Project>
</Project>
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -172,6 +172,9 @@
    <ClCompile Include="CCustomCheckBox.cpp" />
    <ClCompile Include="CCollectionEvent.cpp" />
    <ClCompile Include="CReport.cpp" />
    <ClCompile Include="CReportEditDlg.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="CVariable.cpp" />
    <ClCompile Include="CPageVarialbles.cpp" />
    <ClCompile Include="CPageReport.cpp" />
@@ -233,6 +236,7 @@
    <ClCompile Include="CUserManager2Dlg.cpp" />
    <ClCompile Include="CUserEdit2Dlg.cpp" />
    <ClCompile Include="CUserXLogDlg.cpp" />
    <ClCompile Include="CVariableEditDlg2.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -410,6 +414,9 @@
    <ClInclude Include="CCustomCheckBox.h" />
    <ClInclude Include="CCollectionEvent.h" />
    <ClInclude Include="CReport.h" />
    <ClInclude Include="CReportEditDlg.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="CVariable.h" />
    <ClInclude Include="CPageVarialbles.h" />
    <ClInclude Include="CPageReport.h" />
@@ -509,6 +516,7 @@
    <ClInclude Include="CUserManager2Dlg.h" />
    <ClInclude Include="CUserEdit2Dlg.h" />
    <ClInclude Include="CUserXLogDlg.h" />
    <ClInclude Include="CVariableEditDlg2.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
@@ -552,4 +560,4 @@
      <UniqueIdentifier>{885738f6-3122-4bb9-8308-46b7f692fb13}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
</Project>
</Project>
SourceCode/Bond/Servo/resource.h
Binary files differ
SourceCode/Bond/x64/Debug/ReportList.txt
@@ -26,5 +26,4 @@
50008,(5010)
50009,(5011)
50010,(5012)
50011,(5013)
SourceCode/Bond/x64/Debug/VariableList.txt
@@ -1,39 +1,39 @@
SVID,SV Name,SV Format,SV Remark
100,PortTransferState,U1,0=OutOfService\r\n1=TransferBlocked\r\n2=ReadyToLoad\r\n3=ReadyToUnload\r\n4=InService\r\n5=TransferReady
300,AccessMode,U1,1=Manual\r\n2=Auto
100,PortTransferState,U1,0=OutOfService
300,AccessMode,U1,1=Manual
500,Clock,A50,
600,CurrentControlState,U1,0:Offline:equipment\r\n1:Offline-Attempt\r\n2:Online\r\n3:Offline:host\r\n4:Online:Local\r\n5:Online:Remote
600,CurrentControlState,U1,0:Offline:equipment
601,PreviousControlState,U1,
700,CurrentProcessState,U1,0:DOWN\r\n1:IDLE\r\n2.SETUP\r\n3.EXCUTING\r\n4.MAINTAIN\r\n5.ALARM
700,CurrentProcessState,U1,0:DOWN
701,PreviousProcessState,U1,
800,EFEMPPExecName,A20,
801,EQPPExecName,A20,
2000,RbRAxisTorque,I2,机器人R轴扭矩
2001,RbLAxisTorque,l2,机器人L轴扭矩
2002,RbZAxisTorque,l2,机器人Z轴扭矩
2003,RbTHAxisTorque,l2,机器人TH轴扭矩
2004,RbXAxisTorque,l2,机器人X轴扭矩
2005,AxisX111,l2,X111相机前移栽电机扭矩
2006,AxisX112,l2,X112相机后移栽电机扭矩
2007,AxisU113,l2,U113产品旋转电机扭矩
2008,AxisX114,l2,X114产品左整列电机扭矩
2009,AxisY121,l2,Y121产品右整列电机扭矩
2010,AxisY122,l2,Y122产品前整列电机扭矩
2011,AxisY123,l2,Y123产品后阵列电机扭矩
2012,MainAir,U2,总进气压力值
2013,MainVacuum,l2,总真空压力值
2014,RbMainVacuum,l2,机器人真空值
2015,LPMainVacuum,l2,LP真空值#D265
2016,LPMainAir,U2,LP压空值
2017,ALVacuum,l2,Aligner真空值
2018,FFU1RPM,U2,FFU1转速
2019,FFU2RPM,U2,FFU2转速
2020,FFU3RPM,U2,FFU3转速
2021,FFU4RPM,U2,FFU4转速
2001,RbLAxisTorque,U1,机器人L轴扭矩
2002,RbZAxisTorque,U1,机器人Z轴扭矩
2003,RbTHAxisTorque,U1,机器人TH轴扭矩
2004,RbXAxisTorque,U1,机器人X轴扭矩
2005,AxisX111,U1,X111相机前移栽电机扭矩
2006,AxisX112,U1,X112相机后移栽电机扭矩
2007,AxisU113,U1,U113产品旋转电机扭矩
2008,AxisX114,U1,X114产品左整列电机扭矩
2009,AxisY121,U1,Y121产品右整列电机扭矩
2010,AxisY122,U1,Y122产品前整列电机扭矩
2011,AxisY123,U1,Y123产品后阵列电机扭矩
2012,MainAir,U1,总进气压力值
2013,MainVacuum,U1,总真空压力值
2014,RbMainVacuum,U1,机器人真空值
2015,LPMainVacuum,U1,LP真空值#D265
2016,LPMainAir,U1,LP压空值
2017,ALVacuum,U1,Aligner真空值
2018,FFU1RPM,U1,FFU1转速
2019,FFU2RPM,U1,FFU2转速
2020,FFU3RPM,U1,FFU3转速
2021,FFU4RPM,U1,FFU4转速
2022,ESDValue,I2,静电检测值
2023,OCREnable,U2,"OCR使能:O:开启 1:屏蔽"
2024,CCDEnable,U2,"CCD使能:O:开启 1:屏蔽"
2025,FFUParameter,U2,FFU设定值
2023,OCREnable,U1,"OCR使能:O:开启 1:屏蔽"
2024,CCDEnable,U1,"CCD使能:O:开启 1:屏蔽"
2025,FFUParameter,U1,FFU设定值
5000,CarrierID,A20,卡匣ID
5001,CJobSpace,U1,CJ Space
5002,PJobSpace,U1,PJ Space
@@ -44,6 +44,7 @@
5007,PanelEndID,A20,PanelEndID
5008,CJStartID,A20,CJStartID
5009,CJEndID,A20,CJEndID
5010,UnloadReadyPortId,U2,"Port ID"
5011,LoadReadyPortId,U2,"Port ID"
5012,BlockedPortId,U2,"Port ID"
5010,UnloadReadyPortId,U1,"Port ID"
5011,LoadReadyPortId,U1,"Port ID"
5012,BlockedPortId,U1,"Port ID"
5013,TestVID,U1,测试添加变量55