| | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsEquipmentConstantRequest(const std::vector<unsigned short>& ecids) |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | | int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 13, ++m_nSystemByte); |
| | | for (auto id : ecids) { |
| | | pMessage->getBody()->addU2Item(id, "ECID"); |
| | | } |
| | | m_pActive->sendMessage(pMessage); |
| | | HSMS_Destroy1Message(pMessage); |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsEquipmentConstantSend(const std::vector<std::pair<unsigned short, std::string>>& ecidValues) |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | | int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 15, ++m_nSystemByte); |
| | | ISECS2Item* pBody = pMessage->getBody(); |
| | | for (const auto& kv : ecidValues) { |
| | | ISECS2Item* pEntry = pBody->addItem(); |
| | | pEntry->addU2Item(kv.first, "ECID"); |
| | | pEntry->addItem(kv.second.c_str(), "ECV"); |
| | | } |
| | | m_pActive->sendMessage(pMessage); |
| | | HSMS_Destroy1Message(pMessage); |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsQueryPPIDList() |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | |
| | | int hsmsQueryAllStatusVariables(); // S1F11 |
| | | int hsmsQueryAllDataVariables(); // S1F21 |
| | | int hsmsQueryAllCollectionEvents(); // S1F23 |
| | | int hsmsEquipmentConstantRequest(const std::vector<unsigned short>& ecids); // S2F13 |
| | | int hsmsEquipmentConstantSend(const std::vector<std::pair<unsigned short, std::string>>& ecidValues); // S2F15 |
| | | |
| | | // 查询PPID List |
| | | int hsmsQueryPPIDList(); |
| | |
| | | "\r\n" |
| | | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n" |
| | | "LANGUAGE 4, 2\r\n" |
| | | "#include ""res\\EAPSimulator.rc2"" // 闂?Microsoft Visual C++ 缂傛牞绶惃鍕カ濠?\n" |
| | | "#include ""l.CHS\\afxres.rc"" // 閺嶅洤鍣紒鍕\r\n" |
| | | "#include ""res\\EAPSimulator.rc2"" // 闂?Microsoft Visual C++ 缂傚倹鐗炵欢顐︽儍閸曨喚銈繝?\n" |
| | | "#include ""l.CHS\\afxres.rc"" // 闁哄秴娲ら崳顖滅磼閸曨亝顐?\n" |
| | | "#if !defined(_AFXDLL)\r\n" |
| | | "#include ""l.CHS\\afxribbon.rc"" // MFC 閸旂喕鍏橀崠鍝勬嫲閹貉冨煑閺壜ょカ濠?\n" |
| | | "#include ""l.CHS\\afxribbon.rc"" // MFC 闁告梻鍠曢崗姗€宕犻崫鍕闁硅矇鍐ㄧ厬闁哄銈囥偒婵?\n" |
| | | "#endif\r\n" |
| | | "#endif\r\n" |
| | | "\0" |
| | |
| | | DEFPUSHBUTTON "确定",IDOK,113,41,50,14,WS_GROUP |
| | | END |
| | | |
| | | IDD_EAPSIMULATOR_DIALOG DIALOGEX 0, 0, 469, 292 |
| | | IDD_EAPSIMULATOR_DIALOG DIALOGEX 0, 0, 469, 319 |
| | | STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
| | | EXSTYLE WS_EX_APPWINDOW |
| | | CAPTION "EAPSimulator" |
| | | FONT 9, "MS Shell Dlg", 0, 0, 0x1 |
| | | BEGIN |
| | | DEFPUSHBUTTON "确定",IDOK,246,271,50,14,NOT WS_VISIBLE |
| | | PUSHBUTTON "取消",IDCANCEL,412,271,50,14,NOT WS_VISIBLE |
| | | EDITTEXT IDC_EDIT_LOG,7,218,455,67,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL |
| | | LTEXT "日志:",IDC_STATIC,7,203,24,8 |
| | | GROUPBOX "功能",IDC_STATIC,7,7,455,190 |
| | | DEFPUSHBUTTON "确定",IDOK,246,298,50,14,NOT WS_VISIBLE |
| | | PUSHBUTTON "取消",IDCANCEL,412,298,50,14,NOT WS_VISIBLE |
| | | EDITTEXT IDC_EDIT_LOG,7,245,455,67,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL |
| | | LTEXT "日志:",IDC_STATIC,7,234,24,8 |
| | | GROUPBOX "功能",IDC_STATIC,7,7,455,223 |
| | | LTEXT "IP:",IDC_STATIC,24,20,11,8 |
| | | EDITTEXT IDC_EDIT_IP,39,17,94,14,ES_AUTOHSCROLL |
| | | LTEXT "Port:",IDC_STATIC,141,20,17,8 |
| | |
| | | LEFTMARGIN, 7 |
| | | RIGHTMARGIN, 462 |
| | | TOPMARGIN, 7 |
| | | BOTTOMMARGIN, 285 |
| | | BOTTOMMARGIN, 312 |
| | | END |
| | | |
| | | IDD_DIALOG_TERMINAL_DISPLAY, DIALOG |
| | |
| | | |
| | | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) |
| | | LANGUAGE 4, 2 |
| | | #include "res\EAPSimulator.rc2" // 非 Microsoft Visual C++ 编辑的资源 |
| | | #include "l.CHS\afxres.rc" // 标准组件 |
| | | #include "res\EAPSimulator.rc2" // 闂?Microsoft Visual C++ 缂傛牞绶惃鍕カ濠? |
| | | #include "l.CHS\afxres.rc" // 閺嶅洤鍣紒鍕 |
| | | #if !defined(_AFXDLL) |
| | | #include "l.CHS\afxribbon.rc" // MFC 功能区和控制条资源 |
| | | #include "l.CHS\afxribbon.rc" // MFC 閸旂喕鍏橀崠鍝勬嫲閹貉冨煑閺壜ょカ濠? |
| | | #endif |
| | | #endif |
| | | |
| | |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_SVID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllSvid) |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_DVID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllDvid) |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_CEID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllCeid) |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_ECID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllEcid) |
| | | ON_BN_CLICKED(IDC_BUTTON_SET_ECID, &CEAPSimulatorDlg::OnBnClickedButtonSetEcid) |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_CURRENT_RECIPE, &CEAPSimulatorDlg::OnBnClickedButtonQueryCurrentRecipe) |
| | | ON_BN_CLICKED(IDC_BUTTON_PP_REQUEST, &CEAPSimulatorDlg::OnBnClickedButtonPpRequest) |
| | | END_MESSAGE_MAP() |
| | |
| | | if (hBtn != nullptr) { |
| | | ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE); |
| | | } |
| | | } |
| | | // S2F13 QueryAllECID |
| | | { |
| | | CRect rc(14 + 2 * (140 + 5), 192, 14 + 2 * (140 + 5) + 140, 192 + 14); |
| | | MapDialogRect(&rc); |
| | | HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S2F13_QueryAllECID"), |
| | | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, |
| | | rc.left, rc.top, rc.Width(), rc.Height(), |
| | | m_hWnd, (HMENU)IDC_BUTTON_QUERY_ALL_ECID, AfxGetInstanceHandle(), nullptr); |
| | | if (hBtn != nullptr) { |
| | | ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE); |
| | | } |
| | | } |
| | | // ECID edit + send (S2F15) |
| | | { |
| | | CRect rcEcid(14, 192, 14 + 60, 192 + 14); |
| | | CRect rcEcv(14 + 60 + 4, 192, 14 + 60 + 4 + 60, 192 + 14); |
| | | MapDialogRect(&rcEcid); |
| | | MapDialogRect(&rcEcv); |
| | | HWND hEditEcid = ::CreateWindow(_T("EDIT"), _T(""), WS_CHILD | WS_VISIBLE | WS_BORDER, |
| | | rcEcid.left, rcEcid.top, rcEcid.Width(), rcEcid.Height(), |
| | | m_hWnd, (HMENU)IDC_EDIT_ECID, AfxGetInstanceHandle(), nullptr); |
| | | HWND hEditEcv = ::CreateWindow(_T("EDIT"), _T(""), WS_CHILD | WS_VISIBLE | WS_BORDER, |
| | | rcEcv.left, rcEcv.top, rcEcv.Width(), rcEcv.Height(), |
| | | m_hWnd, (HMENU)IDC_EDIT_ECV, AfxGetInstanceHandle(), nullptr); |
| | | if (hEditEcid) ::SendMessage(hEditEcid, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE); |
| | | if (hEditEcv) ::SendMessage(hEditEcv, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE); |
| | | |
| | | CRect rcBtn(14 + 60 + 4 + 60 + 4, 192, 14 + 60 + 4 + 60 + 4 + 90, 192 + 14); |
| | | MapDialogRect(&rcBtn); |
| | | HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S2F15_SetECID"), |
| | | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, |
| | | rcBtn.left, rcBtn.top, rcBtn.Width(), rcBtn.Height(), |
| | | m_hWnd, (HMENU)IDC_BUTTON_SET_ECID, AfxGetInstanceHandle(), nullptr); |
| | | if (hBtn) ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE); |
| | | } |
| | | // S1F3 CurrentRecipe (EQ specific) combo + button |
| | | { |
| | |
| | | theApp.m_model.m_pHsmsActive->hsmsQueryAllCollectionEvents(); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonQueryAllEcid() |
| | | { |
| | | // empty list => all ECID |
| | | std::vector<unsigned short> ecids; |
| | | ecids.push_back(2000); |
| | | theApp.m_model.m_pHsmsActive->hsmsEquipmentConstantRequest(ecids); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonSetEcid() |
| | | { |
| | | // simple demo: read ECID and value from edit boxes (reuse PPID edit) |
| | | CString sEcid, sVal; |
| | | GetDlgItemText(IDC_EDIT_ECID, sEcid); |
| | | GetDlgItemText(IDC_EDIT_ECV, sVal); |
| | | unsigned short id = static_cast<unsigned short>(_ttoi(sEcid)); |
| | | std::string val = CT2A(sVal); |
| | | std::vector<std::pair<unsigned short, std::string>> kvs; |
| | | if (id != 0) { |
| | | kvs.push_back({ id, val }); |
| | | theApp.m_model.m_pHsmsActive->hsmsEquipmentConstantSend(kvs); |
| | | } |
| | | } |
| | | void CEAPSimulatorDlg::OnBnClickedButtonQueryCurrentRecipe() |
| | | { |
| | | CString sel; |
| | |
| | | afx_msg void OnBnClickedButtonQueryAllSvid(); |
| | | afx_msg void OnBnClickedButtonQueryAllDvid(); |
| | | afx_msg void OnBnClickedButtonQueryAllCeid(); |
| | | afx_msg void OnBnClickedButtonQueryAllEcid(); |
| | | afx_msg void OnBnClickedButtonSetEcid(); |
| | | afx_msg void OnBnClickedButtonQueryCurrentRecipe(); |
| | | afx_msg void OnBnClickedButtonPpRequest(); |
| | | }; |
| | |
| | | #define IDC_EDIT_PPID_REQ 1054 |
| | | #define IDC_BUTTON_PP_REQUEST 1055 |
| | | #define IDC_BUTTON_QUERY_ALL_DVID 1056 |
| | | #define IDC_BUTTON_QUERY_ALL_ECID 1057 |
| | | #define IDC_EDIT_ECID 1058 |
| | | #define IDC_EDIT_ECV 1059 |
| | | #define IDC_BUTTON_SET_ECID 1060 |
| | | |
| | | // Next default values for new objects |
| | | // |
| | |
| | | if (!row.pretty.empty()) { |
| | | CFile file; |
| | | if (file.Open(filePath, CFile::modeCreate | CFile::modeWrite)) { |
| | | file.Write(row.pretty.c_str(), row.pretty.length()); |
| | | file.Write(row.pretty.c_str(), (UINT)row.pretty.length()); |
| | | file.Close(); |
| | | |
| | | CString strSuccess; |
| | |
| | | { |
| | | const ClientInfo& client = clients[i]; |
| | | |
| | | int nItem = m_listClients.InsertItem(i, CString(client.ip.c_str())); |
| | | int nItem = m_listClients.InsertItem((int)i, CString(client.ip.c_str())); |
| | | m_listClients.SetItemText(nItem, 1, CString(std::to_string(client.port).c_str())); |
| | | m_listClients.SetItemText(nItem, 2, client.versionOk ? _T("正常") : _T("异常")); |
| | | m_listClients.SetItemText(nItem, 3, CString(client.status.c_str())); |
| | |
| | | m_listener.onEQOffLine = nullptr; |
| | | m_listener.onEQOnLine = nullptr; |
| | | m_listener.onCommand = nullptr; |
| | | m_listener.onEQConstantRequest = nullptr; |
| | | m_listener.onEQConstantSend = nullptr; |
| | | m_pActiveAction = nullptr; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | |
| | | SERVO::CReport* pReport = new SERVO::CReport(RPTID, vids); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable(vid); |
| | | if (pVariable == nullptr) { |
| | | pVariable = getDataVariable(vid); |
| | | } |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | LOGI("<CHsmsPassive>defineReport RPTID=%d", RPTID); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsPassive::loadEquipmentConstants(const char* pszFilepath) |
| | | { |
| | | if (pszFilepath == NULL) return -1; |
| | | m_strEquipmentConstantFilepath = pszFilepath; |
| | | m_bEquipmentConstantUtf8 = false; |
| | | m_bEquipmentConstantUtf8Bom = false; |
| | | |
| | | CFile file; |
| | | if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) { |
| | | return -1; |
| | | } |
| | | const ULONGLONG nLen = file.GetLength(); |
| | | if (nLen == 0) { |
| | | return -1; |
| | | } |
| | | std::string buffer; |
| | | buffer.resize(static_cast<size_t>(nLen)); |
| | | file.Read(buffer.data(), static_cast<UINT>(nLen)); |
| | | file.Close(); |
| | | |
| | | if (hasUtf8Bom(buffer)) { |
| | | m_bEquipmentConstantUtf8 = true; |
| | | m_bEquipmentConstantUtf8Bom = true; |
| | | buffer = buffer.substr(3); |
| | | } |
| | | else if (isLikelyUtf8(buffer)) { |
| | | m_bEquipmentConstantUtf8 = true; |
| | | } |
| | | CStringW content = m_bEquipmentConstantUtf8 ? Utf8ToWide(buffer.c_str()) : AnsiToWide(buffer.c_str()); |
| | | if (content.IsEmpty()) return -1; |
| | | |
| | | std::wregex pattern(L"^\\d+,[^,]*,[^,]*,([^,]*),.*"); |
| | | std::vector<EquipmentConstantEntry> constants; |
| | | CStringW strLine, strId, strName, strFormat, strRemark, strDefault; |
| | | std::wstringstream ss(content.GetString()); |
| | | auto narrowFromW = [](const CStringW& s) -> std::string { |
| | | int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr); |
| | | if (need <= 0) return {}; |
| | | std::string out(static_cast<size_t>(need - 1), '\0'); |
| | | WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr); |
| | | return out; |
| | | }; |
| | | std::wstring line; |
| | | while (std::getline(ss, line, L'\n')) { |
| | | strLine = line.c_str(); |
| | | strLine.Trim(); |
| | | if (strLine.IsEmpty()) continue; |
| | | if (strLine.Find(L"ECID") == 0) continue; // skip header |
| | | if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) { |
| | | continue; |
| | | } |
| | | int last = 0; |
| | | int idx = strLine.Find(L",", last); |
| | | if (idx < 0) continue; |
| | | strId = strLine.Left(idx); |
| | | last = idx + 1; |
| | | |
| | | idx = strLine.Find(L",", last); |
| | | if (idx < 0) continue; |
| | | strName = strLine.Mid(last, idx - last); |
| | | last = idx + 1; |
| | | |
| | | idx = strLine.Find(L",", last); |
| | | if (idx < 0) continue; |
| | | strFormat = strLine.Mid(last, idx - last); |
| | | last = idx + 1; |
| | | |
| | | idx = strLine.Find(L",", last); |
| | | if (idx < 0) continue; |
| | | strRemark = strLine.Mid(last, idx - last); |
| | | last = idx + 1; |
| | | |
| | | strDefault = strLine.Right(strLine.GetLength() - last); |
| | | |
| | | EquipmentConstantEntry entry; |
| | | entry.id = _wtoi(strId); |
| | | entry.name = narrowFromW(strName); |
| | | entry.format = narrowFromW(strFormat); |
| | | entry.remark = narrowFromW(strRemark); |
| | | entry.value = narrowFromW(strDefault); |
| | | constants.push_back(entry); |
| | | } |
| | | |
| | | if (!constants.empty()) { |
| | | m_equipmentConstants = std::move(constants); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | std::vector<SERVO::CVariable*>& CHsmsPassive::getVariables() |
| | | { |
| | | return m_variabels; |
| | |
| | | if (auto v = getVariable(pszName)) { |
| | | v->setValue(value); |
| | | } |
| | | else if (auto dv = getDataVariable(pszName)) { |
| | | dv->setValue(value); |
| | | } |
| | | Unlock(); |
| | | } |
| | | |
| | |
| | | if (auto v = getVariable(pszName)) { |
| | | v->setValue(value); |
| | | } |
| | | else if (auto dv = getDataVariable(pszName)) { |
| | | dv->setValue(value); |
| | | } |
| | | Unlock(); |
| | | } |
| | | |
| | |
| | | Lock(); |
| | | if (auto v = getVariable(pszName)) { |
| | | v->setValue(vars); |
| | | } |
| | | else if (auto dv = getDataVariable(pszName)) { |
| | | dv->setValue(vars); |
| | | } |
| | | Unlock(); |
| | | } |
| | |
| | | SERVO::CReport* pReport = new SERVO::CReport(_wtoi(strId), vids); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable(vid); |
| | | if (pVariable == nullptr) { |
| | | pVariable = getDataVariable(vid); |
| | | } |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | } |
| | |
| | | SERVO::CReport* pReport = new SERVO::CReport(rptid, vids); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable((int)vid); |
| | | if (pVariable == nullptr) { |
| | | pVariable = getDataVariable((int)vid); |
| | | } |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | } |
| | |
| | | SERVO::CReport* pReport = new SERVO::CReport(rptid, vids); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable((int)vid); |
| | | if (pVariable == nullptr) { |
| | | pVariable = getDataVariable((int)vid); |
| | | } |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | } |
| | |
| | | return ER_NOERROR; |
| | | } |
| | | |
| | | int CHsmsPassive::writeEquipmentConstantsToFile(const std::string& filepath) |
| | | { |
| | | if (filepath.empty()) return -1; |
| | | CFile file; |
| | | if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) { |
| | | return -1; |
| | | } |
| | | const std::string headerAnsi = "ECID,EC Name,EC Format,EC Remark,Default Value\r\n"; |
| | | if (m_bEquipmentConstantUtf8) { |
| | | if (m_bEquipmentConstantUtf8Bom) { |
| | | const BYTE bom[3] = { 0xEF, 0xBB, 0xBF }; |
| | | file.Write(bom, 3); |
| | | } |
| | | CStringA header = AnsiToUtf8(headerAnsi); |
| | | file.Write(header.GetString(), header.GetLength()); |
| | | } |
| | | else { |
| | | file.Write(headerAnsi.data(), (UINT)headerAnsi.size()); |
| | | } |
| | | for (const auto& e : m_equipmentConstants) { |
| | | std::string line; |
| | | line.reserve(128); |
| | | line += std::to_string(e.id); |
| | | line.push_back(','); |
| | | line += e.name; |
| | | line.push_back(','); |
| | | line += e.format; |
| | | line.push_back(','); |
| | | line += e.remark; |
| | | line.push_back(','); |
| | | line += e.value; |
| | | line.append("\r\n"); |
| | | if (m_bEquipmentConstantUtf8) { |
| | | CStringA out = AnsiToUtf8(line); |
| | | file.Write(out.GetString(), out.GetLength()); |
| | | } |
| | | else { |
| | | file.Write(line.data(), (UINT)line.size()); |
| | | } |
| | | } |
| | | file.Close(); |
| | | return 0; |
| | | } |
| | | // S1F21/S1F22 - Data Variable Namelist |
| | | int CHsmsPassive::replyDataVariableNamelistRequest(IMessage* pRecv) |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | // 要获取的常量表表 |
| | | BOOL bCheckData = FALSE; |
| | | std::vector<EQConstant> eqcs; |
| | | { |
| | | ISECS2Item* pItem = pRecv->getBody(); |
| | | int ecidSize = pItem->getSubItemSize(); |
| | | const int ecidSize = pItem ? pItem->getSubItemSize() : 0; |
| | | for (int i = 0; i < ecidSize; i++) { |
| | | EQConstant eqc; |
| | | unsigned short id; |
| | | if (pItem->getSubItemU2(i, id)) { |
| | | EQConstant eqc{}; |
| | | unsigned short id = 0; |
| | | if (pItem && pItem->getSubItemU2(i, id)) { |
| | | eqc.id = id; |
| | | eqcs.push_back(eqc); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来获取机器常量值 |
| | | if (m_listener.onEQConstantRequest != nullptr) { |
| | | m_listener.onEQConstantRequest(this, eqcs); |
| | | // 空列表表示请求全部 ECID |
| | | if (eqcs.empty()) { |
| | | for (const auto& e : m_equipmentConstants) { |
| | | EQConstant eqc{}; |
| | | eqc.id = e.id; |
| | | strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, e.value.c_str()); |
| | | eqcs.push_back(eqc); |
| | | } |
| | | } else { |
| | | for (auto& item : eqcs) { |
| | | auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(), |
| | | [&](const EquipmentConstantEntry& e) { return e.id == item.id; }); |
| | | if (it != m_equipmentConstants.end()) { |
| | | strcpy_s(item.szValue, EQCONSTANT_VALUE_MAX, it->value.c_str()); |
| | | } else { |
| | | item.szValue[0] = '\0'; // unknown -> empty |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // 回复 |
| | | IMessage* pMessage = NULL; |
| | | HSMS_Create1Message(pMessage, m_nSessionId, 1, 14, pRecv->getHeader()->systemBytes); |
| | | HSMS_Create1Message(pMessage, m_nSessionId, 2, 14, pRecv->getHeader()->systemBytes); |
| | | ASSERT(pMessage); |
| | | ISECS2Item* pItem = pMessage->getBody(); |
| | | for (auto& item : eqcs) { |
| | |
| | | } |
| | | |
| | | |
| | | // 要设置的常量表表 |
| | | BOOL bCheckData = FALSE; |
| | | // 要设置的常量表 |
| | | std::vector<EQConstant> eqcs; |
| | | { |
| | | ISECS2Item* pItem = pRecv->getBody(); |
| | | int ecidSize = pItem->getSubItemSize(); |
| | | int ecidSize = pItem ? pItem->getSubItemSize() : 0; |
| | | for (int i = 0; i < ecidSize; i++) { |
| | | ISECS2Item* pItemEqc = pItem->getSubItem(i); |
| | | if (pItemEqc != nullptr) { |
| | | EQConstant eqc; |
| | | unsigned short eqcid; |
| | | const char* pszValue; |
| | | if (pItemEqc->getSubItemU2(0, eqcid) |
| | | && pItemEqc->getSubItemString(1, pszValue)) { |
| | | eqc.id = eqcid; |
| | | strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue); |
| | | eqcs.push_back(eqc); |
| | | } |
| | | ISECS2Item* pItemEqc = pItem ? pItem->getSubItem(i) : nullptr; |
| | | if (pItemEqc == nullptr) continue; |
| | | EQConstant eqc{}; |
| | | unsigned short eqcid = 0; |
| | | const char* pszValue = nullptr; |
| | | if (pItemEqc->getSubItemU2(0, eqcid) |
| | | && pItemEqc->getSubItemString(1, pszValue)) { |
| | | eqc.id = eqcid; |
| | | strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue); |
| | | eqcs.push_back(eqc); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来保存和设置机器常量值 |
| | | std::vector<unsigned int> ecvs; |
| | | if (m_listener.onEQConstantSend != nullptr) { |
| | | m_listener.onEQConstantSend(this, eqcs); |
| | | // 更新内存表并落盘 |
| | | bool changed = false; |
| | | for (auto& item : eqcs) { |
| | | auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(), |
| | | [&](const EquipmentConstantEntry& e) { return e.id == item.id; }); |
| | | if (it != m_equipmentConstants.end()) { |
| | | it->value = item.szValue; |
| | | changed = true; |
| | | } |
| | | } |
| | | if (changed && !m_strEquipmentConstantFilepath.empty()) { |
| | | writeEquipmentConstantsToFile(m_strEquipmentConstantFilepath); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | typedef std::function<void(void* pFrom)> SECSEQOFFLINE; |
| | | typedef std::function<void(void* pFrom, std::vector<EQConstant>&)> SECSEQCONSTANTREQUEST; |
| | | typedef std::function<void(void* pFrom, const char*, std::vector<CommandParameter>&)> SECSCommand; |
| | | typedef std::function<void(void* pFrom, SYSTEMTIME& time)> DATETIMESYNC; |
| | | typedef std::function<void(void* pFrom, bool bEnable, std::vector<unsigned int>& ids)> EDEVENTREPORT; |
| | |
| | | { |
| | | SECSEQOFFLINE onEQOffLine; |
| | | SECSEQOFFLINE onEQOnLine; |
| | | SECSEQCONSTANTREQUEST onEQConstantRequest; |
| | | SECSEQCONSTANTREQUEST onEQConstantSend; |
| | | SECSCommand onCommand; |
| | | DATETIMESYNC onDatetimeSync; |
| | | EDEVENTREPORT onEnableDisableEventReport; |
| | |
| | | int loadVarialbles(const char* pszFilepath); |
| | | // 从文件中加载CDataVariable列表 |
| | | int loadDataVarialbles(const char* pszFilepath); |
| | | // 从文件中加载Equipment Constant列表 |
| | | int loadEquipmentConstants(const char* pszFilepath); |
| | | |
| | | // 取得CVariable列表 |
| | | std::vector<SERVO::CVariable*>& getVariables(); |
| | |
| | | std::vector<unsigned int> parseVidList(CString& strNums); |
| | | int writeVariablesToFile(const std::string& filepath); |
| | | int writeDataVariablesToFile(const std::string& filepath); |
| | | int writeEquipmentConstantsToFile(const std::string& filepath); |
| | | int writeReportsToFile(const std::string& filepath); |
| | | int writeCollectionEventsToFile(const std::string& filepath); |
| | | |
| | |
| | | std::string m_strCollectionEventFilepath; |
| | | bool m_bCollectionUtf8{ false }; |
| | | bool m_bCollectionUtf8Bom{ false }; |
| | | std::string m_strEquipmentConstantFilepath; |
| | | bool m_bEquipmentConstantUtf8{ false }; |
| | | bool m_bEquipmentConstantUtf8Bom{ false }; |
| | | BOOL m_bCimWorking; |
| | | HANDLE m_hCimWorkEvent; |
| | | HANDLE m_hCimWorkThreadHandle; |
| | |
| | | std::vector<SERVO::CVariable*> m_variabels; |
| | | // CDataVariable vector |
| | | std::vector<SERVO::CDataVariable*> m_dataVariabels; |
| | | // Equipment constants |
| | | struct EquipmentConstantEntry { |
| | | unsigned int id{ 0 }; |
| | | std::string name; |
| | | std::string format; |
| | | std::string remark; |
| | | std::string value; |
| | | }; |
| | | std::vector<EquipmentConstantEntry> m_equipmentConstants; |
| | | |
| | | // CReport vector |
| | | std::vector<SERVO::CReport*> m_reports; |
| | |
| | | setControlState(ControlState::OnlineRemote); |
| | | } |
| | | }; |
| | | listener.onEQConstantRequest = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void { |
| | | // 在此填充常量值,目前仅是加1后返回 |
| | | for (auto& item : eqcs) { |
| | | sprintf_s(item.szValue, EQCONSTANT_VALUE_MAX, "Test%d", item.id + 1); |
| | | } |
| | | }; |
| | | listener.onEQConstantSend = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void { |
| | | // 在此保存和设置机器常量值 |
| | | for (auto& item : eqcs) { |
| | | LOGI("onEQConstantRequest: %d, %s", item.id, item.szValue); |
| | | } |
| | | }; |
| | | listener.onDatetimeSync = [&](void* pFrom, SYSTEMTIME& time) -> void { |
| | | LOGI("onDatetimeSync: %d%02d%02d%02d%02d%02d", time.wYear, |
| | | time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond); |
| | |
| | | m_hsmsPassive.loadVarialbles((LPTSTR)(LPCTSTR)strVarialbleFile); |
| | | strVarialbleFile.Format(_T("%s\\DataVariableList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | m_hsmsPassive.loadDataVarialbles((LPTSTR)(LPCTSTR)strVarialbleFile); |
| | | strVarialbleFile.Format(_T("%s\\EquipmentConstantList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | m_hsmsPassive.loadEquipmentConstants((LPTSTR)(LPCTSTR)strVarialbleFile); |
| | | setControlState(m_currentControlState); |
| | | refreshDerivedSVs(); |
| | | m_hsmsPassive.init(this, "APP", 7000); |
| | |
| | | 6701,Measurement_PD_Time,A20,Measurement PD: 时间 |
| | | 6702,Measurement_PD_Value1,A20,Measurement PD: 测量值1 |
| | | 6703,Measurement_PD_Value2,A20,Measurement PD: 测量值2 |
| | | 10200,SlotMap,U2,SlotMap(Scan) |
| | | 10201,SlotMapScan,U2,SlotMap(Scan) |
| | | 10202,SlotMapDownload,U2,SlotMap(Download) |
| | |
| | | SVID,SV Name,SV Format,SV Remark |
| | | 100,PortTransferState,U1,0=OutOfService |
| | | 300,AccessMode,U1,1=Manual |
| | | 500,Clock,A50, |
| | | 600,CurrentControlState,U1,0:Offline:equipment |
| | | 601,PreviousControlState,U1, |
| | | 700,CurrentProcessState,U1,0:DOWN |
| | | 701,PreviousProcessState,U1, |
| | | 800,EFEMPPExecName,A20, |
| | | 801,EQPPExecName,A20, |
| | | 8100,Bonder1CurrentRecipe,A50, |
| | | 8101,Bonder2CurrentRecipe,A50, |
| | | 8102,VacuumBakeCurrentRecipe,A50, |
| | | 8103,BakeCoolingCurrentRecipe,A50, |
| | | 8104,MeasurementCurrentRecipe,A50, |
| | | 8105,EFEMCurrentRecipe,A50, |
| | | 100,PortTransferState,U1,0=OutOfService;1=ReadyToLoad/LoadRequest;2=Loaded;3=InUse/LoadComplete;4=ReadyToUnload/UnloadRequest;5=Empty/UnloadComplete;6=TransferBlocked |
| | | 300,AccessMode,U1,0=Auto;1=Manual |
| | | 500,Clock,A50,Current timestamp string |
| | | 600,CurrentControlState,U1,0=OfflineEquipment;1=OfflineAttempt;2=Online;3=OfflineHost;4=OnlineLocal;5=OnlineRemote |
| | | 601,PreviousControlState,U1,Previous control state (same code set as CurrentControlState) |
| | | 700,CurrentProcessState,U1,0=Ready;1=Processing;2=Complete;3=Error |
| | | 701,PreviousProcessState,U1,Previous process state (0=Ready;1=Processing;2=Complete;3=Error) |
| | | 800,EFEMPPExecName,A20,Current PPExec name from EFEM |
| | | 801,EQPPExecName,A20,Current PPExec name from equipment |
| | | 8100,Bonder1CurrentRecipe,A50,Current recipe for Bonder1 |
| | | 8101,Bonder2CurrentRecipe,A50,Current recipe for Bonder2 |
| | | 8102,VacuumBakeCurrentRecipe,A50,Current recipe for VacuumBake |
| | | 8103,BakeCoolingCurrentRecipe,A50,Current recipe for BakeCooling |
| | | 8104,MeasurementCurrentRecipe,A50,Current recipe for Measurement |
| | | 8105,EFEMCurrentRecipe,A50,Current recipe for EFEM |
| | | 5001,CJobSpace,U1,CJ Space |
| | | 5002,PJobSpace,U1,PJ Space |
| | | 5003,PJQueued,L,PJ Queued |
| | | 5004,PJStartID,A20,PJStartID |
| | | 5005,PJEndID,A20,PJEndID |
| | | 5006,PanelStartID,A20,PanelStartID |
| | | 5007,PanelEndID,A20,PanelEndID |
| | | 5008,CJStartID,A20,CJStartID |
| | | 5009,CJEndID,A20,CJEndID |
| | | 5010,UnloadReadyPortId,U1,Port ID |
| | | 5011,LoadReadyPortId,U1,Port ID |
| | | 5012,BlockedPortId,U1,Port ID |
| | | 5014,VCRPanelID,A20,Panel id, comes from reader |
| | | 5015,ReadyToReleasePortId,U1,Port ID |
| | | 5016,LoadPortNotAssocPortId,U1,Port ID |
| | | 5017,ProcessDataReportText,A50,EV_PROCESS_DATA_REPORT payload string (placeholder) |
| | | 5018,SubEqpName,A20,Equipment name for EV_SubEqpStart/EV_SubEqpEnd |
| | | 5019,SubEqpSlot,U1,Slot number for EV_SubEqpStart/EV_SubEqpEnd |
| | | 5003,PJQueued,L,PJ queued list (IDs) |
| | | 5004,PJStartID,A20,PJ start ID |
| | | 5005,PJEndID,A20,PJ end ID |
| | | 5006,PanelStartID,A20,Panel start ID |
| | | 5007,PanelEndID,A20,Panel end ID |
| | | 5008,CJStartID,A20,CJ start ID |
| | | 5009,CJEndID,A20,CJ end ID |
| | | 5010,UnloadReadyPortId,U1,Port ID (ReadyToUnload) |
| | | 5011,LoadReadyPortId,U1,Port ID (ReadyToLoad) |
| | | 5012,BlockedPortId,U1,Port ID (TransferBlocked) |
| | | 5014,VCRPanelID,A20,Panel ID from reader |
| | | 5015,ReadyToReleasePortId,U1,Port ID (ReadyToRelease) |
| | | 5016,LoadPortNotAssocPortId,U1,Port ID (LoadPortNotAssoc) |
| | | 5017,ProcessDataReportText,A50,EV_PROCESS_DATA_REPORT payload (placeholder) |
| | | 5018,SubEqpName,A20,Sub equipment name for SubEqp events |
| | | 5019,SubEqpSlot,U1,Slot number for SubEqp events |
| | | 5020,PortStateChangePortId,U1,Port ID for PortStateChange |
| | | 5021,PortState,U1,Port transfer/state code for PortStateChange |
| | | 10200,SlotMap,U2,SlotMap(Scan) |
| | | 10201,SlotMapScan,U2,SlotMap(Scan) |
| | | 10202,SlotMapDownload,U2,SlotMap(Download) |