| | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsCreateControlJob(const char* pszControlJobId, std::vector<std::string>& processJobIds) |
| | | { |
| | | char szBuffer[256]; |
| | | sprintf_s(szBuffer, 256, "ControlJob:%s>", pszControlJobId); |
| | | |
| | | IMessage* pMessage = nullptr; |
| | | int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 14 | REPLY, 9, ++m_nSystemByte); |
| | | pMessage->getBody()->addItem(szBuffer, "OBJSPEC"); |
| | | pMessage->getBody()->addItem("ControlJob", "OBJTYPE"); |
| | | auto itemAttrs = pMessage->getBody()->addItem(); |
| | | |
| | | { |
| | | auto itemAttr = itemAttrs->addItem(); |
| | | itemAttr->addItem("Priority", "ATTRID"); |
| | | itemAttr->addU1Item(8, "ATTRDATA"); |
| | | } |
| | | |
| | | { |
| | | auto itemAttr = itemAttrs->addItem(); |
| | | itemAttr->addItem("weight", "ATTRID"); |
| | | itemAttr->addF4Item(60.5, "ATTRDATA"); |
| | | } |
| | | |
| | | { |
| | | auto itemAttr = itemAttrs->addItem(); |
| | | itemAttr->addItem("tel", "ATTRID"); |
| | | itemAttr->addItem("15919875007", "ATTRDATA"); |
| | | } |
| | | |
| | | { |
| | | auto itemAttr = itemAttrs->addItem(); |
| | | itemAttr->addItem("PRJOBLIST", "ATTRID"); |
| | | auto itemProcessJobs = itemAttr->addItem(); |
| | | for (auto& item : processJobIds) { |
| | | itemProcessJobs->addItem(item.c_str(), ""); |
| | | } |
| | | } |
| | | |
| | | m_pActive->sendMessage(pMessage); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::replyAck0(IMessage* pMessage) |
| | | { |
| | | return 0; |
| | |
| | | // S16F15 |
| | | int hsmsPRJobMultiCreate(std::vector<SERVO::CProcessJob*>& pjs); |
| | | |
| | | // S14F9 |
| | | int hsmsCreateControlJob(const char* pszControlJobId, std::vector<std::string>& processJobIds); |
| | | |
| | | // éè¿çreply彿° |
| | | void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName); |
| | | |
| | |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_CJ_SPACE, &CEAPSimulatorDlg::OnBnClickedButtonQueryCjSpace) |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_PJ_SPACE, &CEAPSimulatorDlg::OnBnClickedButtonQueryPjSpace) |
| | | ON_BN_CLICKED(IDC_BUTTON_CREATE_PJ, &CEAPSimulatorDlg::OnBnClickedButtonCreatePj) |
| | | ON_BN_CLICKED(IDC_BUTTON_CREATE_CJ, &CEAPSimulatorDlg::OnBnClickedButtonCreateCj) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | GetDlgItem(IDC_BUTTON_QUERY_CJ_SPACE)->EnableWindow(enabled); |
| | | GetDlgItem(IDC_BUTTON_QUERY_PJ_SPACE)->EnableWindow(enabled); |
| | | GetDlgItem(IDC_BUTTON_CREATE_PJ)->EnableWindow(enabled); |
| | | GetDlgItem(IDC_BUTTON_CREATE_CJ)->EnableWindow(enabled); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonConnect() |
| | |
| | | CPJsDlg dlg; |
| | | dlg.DoModal(); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonCreateCj() |
| | | { |
| | | std::vector<std::string> processJobIds = {"PJ0001", "PJ0003"}; |
| | | theApp.m_model.m_pHsmsActive->hsmsCreateControlJob("CJ5007", processJobIds); |
| | | } |
| | |
| | | afx_msg void OnBnClickedButtonQueryCjSpace(); |
| | | afx_msg void OnBnClickedButtonQueryPjSpace(); |
| | | afx_msg void OnBnClickedButtonCreatePj(); |
| | | afx_msg void OnBnClickedButtonCreateCj(); |
| | | }; |
| | |
| | | #define IDC_BUTTON_QUERY_PJ_SPACE 1038 |
| | | #define IDC_BUTTON_CREATE_PJ 1039 |
| | | #define IDC_BUTTON_ADD 1040 |
| | | #define IDC_BUTTON_CREATE_PJ2 1040 |
| | | #define IDC_BUTTON_CREATE_CJ 1040 |
| | | #define IDC_BUTTON_DELETE 1041 |
| | | |
| | | // Next default values for new objects |
| | |
| | | virtual void setBinary(const char* pszData, unsigned int len, const char* pszNote) = 0; |
| | | virtual void setString(const char* pszText, const char* pszNote) = 0; |
| | | virtual void setU1(unsigned char value, const char* pszNote) = 0; |
| | | virtual void setBool(bool value, const char* pszNote) = 0; |
| | | virtual ISECS2Item* addItem() = 0; |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CControlJob.h" |
| | | #include <cctype> |
| | | |
| | | static inline std::string trimCopy(std::string s) { |
| | | auto notspace = [](int ch) { return !std::isspace(ch); }; |
| | | s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace)); |
| | | s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end()); |
| | | return s; |
| | | } |
| | | |
| | | namespace SERVO { |
| | | CControlJob::CControlJob(std::string cjId) |
| | | : m_cjId(trimCopy(std::move(cjId))) |
| | | { |
| | | clampString(m_cjId, MAX_ID_LEN); |
| | | } |
| | | |
| | | CControlJob::CControlJob(CControlJob& src) |
| | | { |
| | | m_cjId = src.m_cjId; |
| | | clampString(m_cjId, MAX_ID_LEN); |
| | | m_priority = src.m_priority; |
| | | m_pjIds = src.m_pjIds; |
| | | m_state = src.m_state; |
| | | m_failReason = src.m_failReason; |
| | | m_tQueued = src.m_tQueued; |
| | | m_tStart = src.m_tStart; |
| | | m_tEnd = src.m_tEnd; |
| | | } |
| | | |
| | | bool CControlJob::addPJ(const std::string& pjId) { |
| | | if (pjId.empty()) return false; |
| | | auto id = pjId; |
| | | auto it = std::find(m_pjIds.begin(), m_pjIds.end(), id); |
| | | if (it != m_pjIds.end()) return false; |
| | | clampString(id, MAX_ID_LEN); |
| | | m_pjIds.push_back(std::move(id)); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::addPJs(const std::vector<std::string>& ids) { |
| | | bool added = false; |
| | | for (auto& s : ids) added |= addPJ(s); |
| | | return added; |
| | | } |
| | | |
| | | bool CControlJob::setPJs(const std::vector<CProcessJob*>& pjs) |
| | | { |
| | | m_pjs = pjs; |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::removePJ(const std::string& pjId) { |
| | | auto it = std::find(m_pjIds.begin(), m_pjIds.end(), pjId); |
| | | if (it == m_pjIds.end()) return false; |
| | | m_pjIds.erase(it); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::containsPJ(const std::string& pjId) const { |
| | | return std::find(m_pjIds.begin(), m_pjIds.end(), pjId) != m_pjIds.end(); |
| | | } |
| | | |
| | | const std::vector<CControlJob::ValidationIssue>& CControlJob::issues() |
| | | { |
| | | return m_issues; |
| | | } |
| | | |
| | | bool CControlJob::validateForCreate( |
| | | const std::function<bool(uint32_t& code, std::string& msg)>& canCreateCjFn, |
| | | const std::function<bool(const std::string&)>& getPjExistsFn, |
| | | const std::function<bool(const std::string&)>& canJoinFn |
| | | ) |
| | | { |
| | | m_issues.clear(); |
| | | |
| | | auto add = [&](uint32_t code, std::string msg) { m_issues.push_back({ code, std::move(msg) }); }; |
| | | |
| | | // æ¯å¦è½å建CJ, ç±ä¸å±æ ¹æ®å½åä»»å¡ï¼æºå¨ç¶æçæ£éª |
| | | uint32_t cc; |
| | | std::string mm; |
| | | if (!canCreateCjFn(cc, mm)) { |
| | | add(cc, mm); |
| | | } |
| | | |
| | | |
| | | // CJID åºç¡æ ¡éª |
| | | if (m_cjId.empty()) add(1101, "CJID empty"); |
| | | if (!asciiPrintable(m_cjId)) add(1102, "CJID has non-printable chars"); |
| | | |
| | | // PJ åè¡¨æ ¡éª |
| | | if (m_pjIds.empty()) add(1110, "PRJOBLIST empty"); |
| | | for (const auto& pj : m_pjIds) { |
| | | if (!getPjExistsFn(pj)) add(1111, "PJ not found: " + pj); |
| | | else if (!canJoinFn(pj)) add(1112, "PJ not joinable: " + pj); |
| | | } |
| | | |
| | | return m_issues.empty(); |
| | | } |
| | | |
| | | // åºç¨å建/æ´æ°ï¼ç¨äº S14F9 â S14F10 è·¯å¾ï¼ |
| | | CControlJob::CreateResult |
| | | CControlJob::applyCreate( |
| | | const CreateRequest& req, |
| | | const std::function<bool(const std::string&)>& getPjExistsFn, |
| | | const std::function<bool(const std::string&)>& canJoinFn |
| | | ) |
| | | { |
| | | CreateResult r; |
| | | |
| | | // è¦çä¼å
级ï¼å¦æä¾ï¼ |
| | | if (req.priority.has_value()) { |
| | | m_priority = *req.priority; |
| | | } |
| | | |
| | | // é PJ å¤å® |
| | | for (const auto& pjIdRaw : req.requestedPjIds) { |
| | | std::string pjId = trimCopy(pjIdRaw); |
| | | clampString(pjId, MAX_ID_LEN); |
| | | |
| | | if (!getPjExistsFn(pjId)) { |
| | | r.errors.push_back({ 2001, "PRJOBLIST: " + pjId + " not found" }); |
| | | continue; |
| | | } |
| | | if (!canJoinFn(pjId)) { |
| | | r.errors.push_back({ 2002, "PRJOBLIST: " + pjId + " not joinable (state)" }); |
| | | continue; |
| | | } |
| | | if (containsPJ(pjId)) { |
| | | // å·²å¨å表ï¼è§ä½æåï¼å¹çï¼ |
| | | r.acceptedPjIds.push_back(pjId); |
| | | continue; |
| | | } |
| | | // å å
¥ CJ |
| | | m_pjIds.push_back(pjId); |
| | | r.acceptedPjIds.push_back(std::move(pjId)); |
| | | } |
| | | |
| | | // å½å¹¶ ACK |
| | | if (r.errors.empty()) r.objack = 0; // å
¨æå |
| | | else if (!r.acceptedPjIds.empty()) r.objack = 1; // é¨åæå |
| | | else r.objack = 2; // å
¨å¤±è´¥ |
| | | |
| | | return r; |
| | | } |
| | | |
| | | // ââ ç¶ææº ââ // |
| | | bool CControlJob::queue() { |
| | | if (m_state != CJState::NoState) return false; |
| | | markQueued(); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::start() { |
| | | if (m_state != CJState::Queued) return false; |
| | | m_state = CJState::Executing; |
| | | if (!m_tStart.has_value()) markStart(); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::pause() { |
| | | if (m_state != CJState::Executing) return false; |
| | | m_state = CJState::Paused; |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::resume() { |
| | | if (m_state != CJState::Paused) return false; |
| | | m_state = CJState::Executing; |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::complete() { |
| | | if (m_state != CJState::Executing && m_state != CJState::Paused) return false; |
| | | m_state = CJState::Completed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::abort() { |
| | | if (m_state == CJState::Completed || m_state == CJState::Aborted || m_state == CJState::Failed) |
| | | return false; |
| | | m_state = CJState::Aborted; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CControlJob::fail(std::string reason) { |
| | | m_failReason = trimCopy(reason); |
| | | clampString(m_failReason, 128); |
| | | m_state = CJState::Failed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | // ââ èå宿夿 ââ // |
| | | bool CControlJob::tryAggregateComplete( |
| | | const std::function<bool(const std::string&)>& isPjCompletedFn |
| | | ) { |
| | | if (m_pjIds.empty()) return false; |
| | | for (const auto& pj : m_pjIds) { |
| | | if (!isPjCompletedFn(pj)) return false; |
| | | } |
| | | // ææ PJ 已宿 â CJ 宿 |
| | | return complete(); |
| | | } |
| | | |
| | | // ââ æ¶é´æ³ ââ // |
| | | void CControlJob::markQueued() { m_state = CJState::Queued; m_tQueued = std::chrono::system_clock::now(); } |
| | | void CControlJob::markStart() { m_tStart = std::chrono::system_clock::now(); } |
| | | void CControlJob::markEnd() { m_tEnd = std::chrono::system_clock::now(); } |
| | | |
| | | // ââ å·¥å
· ââ // |
| | | void CControlJob::clampString(std::string& s, size_t maxLen) { |
| | | if (s.size() > maxLen) s.resize(maxLen); |
| | | } |
| | | |
| | | bool CControlJob::asciiPrintable(const std::string& s) { |
| | | return std::all_of(s.begin(), s.end(), [](unsigned char c) { |
| | | return c >= 0x20 && c <= 0x7E; |
| | | }); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <string> |
| | | #include <vector> |
| | | #include <algorithm> |
| | | #include <cstdint> |
| | | #include <optional> |
| | | #include <chrono> |
| | | #include <functional> |
| | | #include "ProcessJob.h" |
| | | |
| | | |
| | | // ââ æ å/项ç®å
约å®ç屿§åï¼A:40ï¼ââ |
| | | // 说æï¼ä¸ä»¥ç©ºæ ¼å¼å¤´/ç»å°¾ï¼å符èå´ 0x20-0x7Eï¼ä¸ä¸è½å
å« > : ? * ~ |
| | | inline constexpr const char* CJ_ATTR_CJID = "CJID"; // A:n |
| | | inline constexpr const char* CJ_ATTR_PRIORITY = "Priority"; // U1 |
| | | inline constexpr const char* CJ_ATTR_PRJOBLIST = "PRJOBLIST"; // L:n of A:n (PJID[]) |
| | | |
| | | namespace SERVO { |
| | | /// CJ ç¶æï¼è´´è¿ E40 è¯ä¹ï¼ |
| | | enum class CJState : uint8_t { |
| | | NoState = 0, |
| | | Queued, |
| | | Executing, |
| | | Paused, |
| | | Completed, |
| | | Aborted, |
| | | Failed |
| | | }; |
| | | |
| | | /// å建/ä¿®æ¹ç»æä¸çé误项 |
| | | struct CJError { |
| | | uint16_t code; // èªå®ä¹é误ç ï¼ä¾ï¼2001=PJ_NOT_FOUND, 2002=NOT_JOINABLEï¼ |
| | | std::string text; // 建议å
å«å®ä½ä¿¡æ¯ï¼ATTRID/PJIDï¼ |
| | | }; |
| | | |
| | | /// CControlJobï¼Control Job 管çç±» |
| | | class CControlJob { |
| | | public: |
| | | explicit CControlJob(std::string cjId); |
| | | explicit CControlJob(CControlJob& src); |
| | | |
| | | // ââ åºæ¬å±æ§ ââ // |
| | | const std::string& id() const noexcept { return m_cjId; } |
| | | CJState state() const noexcept { return m_state; } |
| | | uint8_t priority() const noexcept { return m_priority; } |
| | | void setPriority(uint8_t p) noexcept { m_priority = p; } |
| | | |
| | | // ââ PJ å表维æ¤ï¼å»éï¼ââ // |
| | | bool addPJ(const std::string& pjId); // å·²åå¨åä¸é夿·»å |
| | | bool addPJs(const std::vector<std::string>& ids); // è¿åæ¯å¦ææ°å¢ |
| | | bool removePJ(const std::string& pjId); // åå¨åç§»é¤ |
| | | bool containsPJ(const std::string& pjId) const; |
| | | const std::vector<std::string>& pjIds() const noexcept { return m_pjIds; } |
| | | bool setPJs(const std::vector<CProcessJob*>& pjs); |
| | | void clearPJs() { m_pjIds.clear(); } |
| | | |
| | | // ââ æ ¡éª ââ // |
| | | struct ValidationIssue { uint32_t code; std::string text; }; |
| | | |
| | | // æ ¡éª CJ æ¯å¦å¯å建/æ´æ°ï¼ä¾å¦ï¼PJ æ¯å¦åå¨ãæ¯å¦å¯å å
¥ï¼ |
| | | // getPjExistsFn(pjId)->boolï¼PJ æ¯å¦åå¨ |
| | | // canJoinFn(pjId)->bool ï¼PJ å½åæ¯å¦å
许å å
¥ CJï¼å¦ PJ ç¶æä¸º Queued çï¼ |
| | | bool validateForCreate( |
| | | const std::function<bool(uint32_t& code, std::string& msg)>& canCreateCjFn, |
| | | const std::function<bool(const std::string&)>& getPjExistsFn, |
| | | const std::function<bool(const std::string&)>& canJoinFn |
| | | ); |
| | | const std::vector<CControlJob::ValidationIssue>& CControlJob::issues(); |
| | | |
| | | // ââ S14F9 â S14F10 çâåºç¨ç»æâ模å ââ // |
| | | struct CreateRequest { |
| | | std::optional<uint8_t> priority; // è¥æåè¦ç |
| | | std::vector<std::string> requestedPjIds;// æ³è¦ç»å®ç PJ å表 |
| | | }; |
| | | struct CreateResult { |
| | | std::vector<std::string> acceptedPjIds; // æåç»å®ç PJï¼ç¨äºåæ¾ PRJOBLISTï¼ |
| | | std::vector<CJError> errors; // 失败项ï¼å« PJID 说æï¼ |
| | | uint8_t objack{ 0 }; // 0=å
¨æå, 1=é¨åæå, 2=å
¨å¤±è´¥ |
| | | }; |
| | | |
| | | // åºç¨å建/æ´æ°è¯·æ±ï¼åªç»å®å
许ç PJï¼å¹¶çæ OBJACK/é误æ¸
å |
| | | // getPjExistsFn / canJoinFn åä¸ |
| | | CreateResult applyCreate( |
| | | const CreateRequest& req, |
| | | const std::function<bool(const std::string&)>& getPjExistsFn, |
| | | const std::function<bool(const std::string&)>& canJoinFn |
| | | ); |
| | | |
| | | // ââ ç¶ææº ââ // |
| | | bool queue(); // NoState -> Queued |
| | | bool start(); // Queued -> Executing |
| | | bool pause(); // Executing -> Paused |
| | | bool resume(); // Paused -> Executing |
| | | bool complete(); // Executing/Paused -> Completed |
| | | bool abort(); // éç»æ -> Aborted |
| | | bool fail(std::string reason); // ä»»æ -> Failed |
| | | |
| | | const std::string& failReason() const noexcept { return m_failReason; } |
| | | |
| | | // ââ æ¶é´æ³ ââ // |
| | | std::optional<std::chrono::system_clock::time_point> tQueued() const { return m_tQueued; } |
| | | std::optional<std::chrono::system_clock::time_point> tStart() const { return m_tStart; } |
| | | std::optional<std::chrono::system_clock::time_point> tEnd() const { return m_tEnd; } |
| | | |
| | | // ââ æ±æ»ç¶æè¾
å©ï¼å¯éï¼ââ // |
| | | // æ ¹æ®å¤é¨æä¾çâPJ æ¯å¦å·²å®æâ夿ï¼å°è¯æ CJ èå置为 Completedã |
| | | // isPjCompletedFn(pjId)->bool |
| | | bool tryAggregateComplete(const std::function<bool(const std::string&)>& isPjCompletedFn); |
| | | |
| | | // å·¥å
·ï¼ç»ä¸å符串éå¶ |
| | | static void clampString(std::string& s, size_t maxLen); |
| | | static bool asciiPrintable(const std::string& s); |
| | | |
| | | private: |
| | | void markQueued(); |
| | | void markStart(); |
| | | void markEnd(); |
| | | |
| | | private: |
| | | // ââ æ è¯ & é
ç½® ââ // |
| | | std::string m_cjId; |
| | | uint8_t m_priority{ 5 }; // 缺çä¼å
级ï¼èªå®ï¼ |
| | | |
| | | // ââ ç»æ ââ // |
| | | std::vector<std::string> m_pjIds; |
| | | std::vector<CProcessJob*> m_pjs; |
| | | |
| | | // ââ ç¶æ / ææ¬ ââ // |
| | | CJState m_state{ CJState::NoState }; |
| | | std::string m_failReason; |
| | | |
| | | // ââ æ¶é´æ³ ââ // |
| | | std::optional<std::chrono::system_clock::time_point> m_tQueued; |
| | | std::optional<std::chrono::system_clock::time_point> m_tStart; |
| | | std::optional<std::chrono::system_clock::time_point> m_tEnd; |
| | | |
| | | // ââ ç»ä¸çº¦æ ââ // |
| | | static constexpr size_t MAX_ID_LEN = 64; // CJID / PJID ç |
| | | |
| | | // é误å表 |
| | | std::vector<ValidationIssue> m_issues; |
| | | }; |
| | | } |
| | | |
| | |
| | | m_bContinuousTransfer = false; |
| | | m_nContinuousTransferCount = 0; |
| | | m_nContinuousTransferStep = CTStep_Unknow; |
| | | m_pControlJob = nullptr; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | | CMaster::~CMaster() |
| | | { |
| | | // éæ¾Jobç¸å
³ |
| | | for (auto item : m_processJobs) { |
| | | delete item; |
| | | } |
| | | m_processJobs.clear(); |
| | | if (m_pControlJob != nullptr) { |
| | | delete m_pControlJob; |
| | | m_pControlJob = nullptr; |
| | | } |
| | | |
| | | if (m_hEventReadBitsThreadExit[0] != nullptr) { |
| | | ::CloseHandle(m_hEventReadBitsThreadExit[0]); |
| | |
| | | m_nContinuousTransferCount = round; |
| | | } |
| | | |
| | | int CMaster::setProcessJobs(std::vector<SERVO::CProcessJob*>& pjs) |
| | | int CMaster::setProcessJobs(std::vector<CProcessJob*>& pjs) |
| | | { |
| | | std::vector<SERVO::CProcessJob*> temp; |
| | | for (auto p : pjs) { |
| | | if (p->validate(*this)) { |
| | | p->queue(); |
| | | temp.push_back(p); |
| | | } |
| | | } |
| | |
| | | return m_processJobs.size(); |
| | | } |
| | | |
| | | std::vector<SERVO::CProcessJob*>& CMaster::getProcessJobs() |
| | | std::vector<CProcessJob*>& CMaster::getProcessJobs() |
| | | { |
| | | return m_processJobs; |
| | | } |
| | | |
| | | CProcessJob* CMaster::getProcessJob(const std::string& id) |
| | | { |
| | | for (auto item : m_processJobs) { |
| | | if (item->id().compare(id) == 0) return item; |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CMaster::setControlJob(CControlJob& controlJob) |
| | | { |
| | | // åè°ï¼æ¯å¦åå建ControlJob |
| | | auto canCreateCjFn = [&](uint32_t& cc, std::string& mm) -> bool { |
| | | if (m_pControlJob != nullptr) { |
| | | cc = 1100; |
| | | mm = "å½åControlJobæªç»æ¹ï¼ä¸è½å建æ°çControlJob"; |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | |
| | | // åè°ï¼æ¯å¦åå¨ |
| | | auto pjExists = [&](const std::string& id) -> bool { |
| | | return getProcessJob(id) != nullptr; |
| | | }; |
| | | |
| | | // åè°ï¼æ¯å¦å¯å å
¥ CJï¼è¿éå®ä¹ï¼å¿
é¡»æ¯ Queuedï¼ |
| | | auto pjJoinable = [&](const std::string& id) -> bool { |
| | | auto pj = getProcessJob(id); |
| | | if (pj == nullptr) return false; |
| | | return pj->state() == PJState::Queued; |
| | | }; |
| | | |
| | | bool bRet = controlJob.validateForCreate(canCreateCjFn, pjExists, pjJoinable); |
| | | if (!bRet) return -1; |
| | | |
| | | std::vector<CProcessJob*> temps; |
| | | m_pControlJob = new CControlJob(controlJob); |
| | | auto pjIds = controlJob.pjIds(); |
| | | for (auto id : pjIds) { |
| | | auto pj = getProcessJob(id); |
| | | if (pj != nullptr) { |
| | | temps.push_back(pj); |
| | | } |
| | | } |
| | | m_pControlJob->setPJs(temps); |
| | | return 0; |
| | | } |
| | | |
| | | CLoadPort* CMaster::getPortWithCarrierId(const std::string& carrierId) const |
| | | { |
| | | CLoadPort* pPort; |
| | |
| | | #include "CCLinkIEControl.h" |
| | | #include "CRobotTask.h" |
| | | #include "ProcessJob.h" |
| | | #include "CControlJob.h" |
| | | |
| | | |
| | | #define CTStep_Unknow 0 |
| | |
| | | int carrierRelease(unsigned int port); |
| | | int getContinuousTransferCount(); |
| | | void setContinuousTransferCount(int round); |
| | | int setProcessJobs(std::vector<SERVO::CProcessJob*>& pjs); |
| | | std::vector<SERVO::CProcessJob*>& getProcessJobs(); |
| | | int setProcessJobs(std::vector<CProcessJob*>& pjs); |
| | | std::vector<CProcessJob*>& getProcessJobs(); |
| | | CProcessJob* getProcessJob(const std::string& id); |
| | | int setControlJob(CControlJob& controlJob); |
| | | CLoadPort* getPortWithCarrierId(const std::string& carrierId) const; |
| | | |
| | | private: |
| | |
| | | private: |
| | | bool m_bEnableEventReport; |
| | | bool m_bEnableAlarmReport; |
| | | SERVO::CControlJob* m_pControlJob; |
| | | std::vector<SERVO::CProcessJob*> m_processJobs; |
| | | }; |
| | | } |
| | |
| | | else if (nStream == 10 && pHeader->function == 3) { |
| | | replyTerminalDisplay(pMessage); |
| | | } |
| | | else if (nStream == 14 && pHeader->function == 9) { |
| | | replyCreateObj(pMessage); |
| | | } |
| | | else if (nStream == 16 && pHeader->function == 15) { |
| | | replyPRJobMultiCreate(pMessage); |
| | | } |
| | |
| | | return 0; |
| | | } |
| | | |
| | | // S14F9 |
| | | int CHsmsPassive::replyCreateObj(IMessage* pRecv) |
| | | { |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | | return ER_NOTSELECT; |
| | | } |
| | | ISECS2Item* pBody = pRecv->getBody(); |
| | | if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR; |
| | | |
| | | |
| | | // æ¯å¦å建æåå¹¶åå¤å夿¥æ |
| | | bool bCreateOk = false; |
| | | IMessage* pReply = NULL; |
| | | HSMS_Create1Message(pReply, m_nSessionId, 14, 10, ++m_nSystemByte); |
| | | ASSERT(pReply); |
| | | |
| | | |
| | | |
| | | // è§£éæ°æ®ï¼å¾å°ControlJob |
| | | ISECS2Item* pItemAttrs, * pItemAttr, *pItemAttrData; |
| | | const char* pszObjSpec, *pszObjType, *pszAttrId, *pszProcessJobId; |
| | | std::string strObjName, strObjId; |
| | | if (!pBody->getSubItemString(0, pszObjSpec)) return ER_PARAM_ERROR; |
| | | if (!pBody->getSubItemString(1, pszObjType)) return ER_PARAM_ERROR; |
| | | |
| | | pReply->getBody()->addItem(pszObjSpec, "OBJSPEC"); |
| | | ISECS2Item* pReplyItemAttrs = pReply->getBody()->addItem(); |
| | | ISECS2Item* pReplyItemAcks = pReply->getBody()->addItem(); |
| | | ISECS2Item* pReplyItemAck = pReplyItemAcks->addU1Item(0, "OBJACK"); |
| | | ISECS2Item* pReplyItemErrs = pReplyItemAcks->addItem(); |
| | | |
| | | // å½ååªå¤çç±»å为ControlJob |
| | | if (_strcmpi(pszObjType, "ControlJob") == 0) { |
| | | |
| | | // ç±»id |
| | | std::regex re("^([^:]+):([^>]+)>"); |
| | | std::smatch match; |
| | | std::string strObjSpec(pszObjSpec); |
| | | if (!std::regex_search(strObjSpec, match, re)) { |
| | | ISECS2Item* pItemError = pReplyItemErrs->addItem(); |
| | | pItemError->addU4Item(2001, "ERRCODE"); |
| | | pItemError->addItem("åæ°ææ¥æä¸æ£ç¡®", "ERRTEXT"); |
| | | goto MYREPLY; |
| | | } |
| | | |
| | | if (match[1].compare("ControlJob") != 0) { |
| | | ISECS2Item* pItemError = pReplyItemErrs->addItem(); |
| | | pItemError->addU4Item(2001, "ERRCODE"); |
| | | pItemError->addItem("䏿¯æçOBJ", "ERRTEXT"); |
| | | goto MYREPLY; |
| | | } |
| | | strObjId = match[2]; |
| | | |
| | | // å建类CControlJob |
| | | SERVO::CControlJob controlJob(strObjId); |
| | | |
| | | // ç±»å±æ§ |
| | | pItemAttrs = pBody->getSubItem(2); |
| | | if (pItemAttrs == nullptr) return ER_PARAM_ERROR; |
| | | for (int i = 0; i < pItemAttrs->getSubItemSize(); i++) { |
| | | pItemAttr = pItemAttrs->getSubItem(i); |
| | | if (pItemAttr == nullptr) continue; |
| | | if (!pItemAttr->getSubItemString(0, pszAttrId)) continue; |
| | | if (_strcmpi(pszAttrId, CJ_ATTR_PRIORITY) == 0) { |
| | | uint8_t priority; |
| | | if (pItemAttr->getSubItemU1(1, priority)) { |
| | | controlJob.setPriority(priority); |
| | | } |
| | | } |
| | | else if (_strcmpi(pszAttrId, CJ_ATTR_PRJOBLIST) == 0) { |
| | | pItemAttrData = pItemAttr->getSubItem(1); |
| | | if (pItemAttrData != nullptr && pItemAttrData->getType() == SITYPE::L) { |
| | | for (int i = 0; i < pItemAttrData->getSubItemSize(); i++) { |
| | | if (pItemAttrData->getSubItemString(i, pszProcessJobId)) { |
| | | std::string strProcessJobId(pszProcessJobId); |
| | | controlJob.addPJ(strProcessJobId); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | ASSERT(m_listener.onControlJobCreate != nullptr); |
| | | int nRet = m_listener.onControlJobCreate(this, controlJob); |
| | | bCreateOk = nRet == 0; |
| | | |
| | | // æ·»å æ°å»ºç±»çåç§å±æ§å°å夿¥æä¸ |
| | | if(bCreateOk) { |
| | | { |
| | | ISECS2Item* pReplyItemAttr = pReplyItemAttrs->addItem(); |
| | | pReplyItemAttr->addItem(CJ_ATTR_PRIORITY, "ATTRID"); |
| | | pReplyItemAttr->addU1Item(controlJob.priority(), "ATTRDATA"); |
| | | } |
| | | |
| | | { |
| | | ISECS2Item* pReplyItemAttr = pReplyItemAttrs->addItem(); |
| | | pReplyItemAttr->addItem(CJ_ATTR_PRJOBLIST, "ATTRID"); |
| | | ISECS2Item* pItemPjs = pReplyItemAttr->addItem(); |
| | | auto pjIds = controlJob.pjIds(); |
| | | for (auto id : pjIds) { |
| | | pItemPjs->addItem(id.c_str(), "PRJOBID"); |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | auto issues = controlJob.issues(); |
| | | for (auto i : issues) { |
| | | ISECS2Item* pItemError = pReplyItemErrs->addItem(); |
| | | pItemError->addU4Item(i.code, "ERRCODE"); |
| | | pItemError->addItem(i.text.c_str(), "ERRTEXT"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | else { |
| | | ISECS2Item* pItemError = pReplyItemErrs->addItem(); |
| | | pItemError->addU4Item(2001, "ERRCODE"); |
| | | pItemError->addItem("䏿¯æçOBJ", "ERRTEXT"); |
| | | } |
| | | |
| | | |
| | | // å®åæ¥æå¹¶åå¤ |
| | | MYREPLY: |
| | | pReplyItemAck->setU1(bCreateOk ? 0 : 1, "OBJACK"); |
| | | m_pPassive->sendMessage(pReply); |
| | | LOGI("<HSMS>[SECS Msg SEND]S14F10 (SysByte=%u)", pReply->getHeader()->systemBytes); |
| | | HSMS_Destroy1Message(pReply); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | // S16F15 |
| | | int CHsmsPassive::replyPRJobMultiCreate(IMessage* pRecv) |
| | | { |
| | |
| | | ISECS2Item* pItemErrors = pMessage->getBody()->addItem(); |
| | | bool bHasError = false; |
| | | for (auto p : pjs) { |
| | | if (p->issue().empty()) { |
| | | if (p->issues().empty()) { |
| | | pItemPrjobIds->addItem(p->id().c_str(), "PRJOBID"); |
| | | } |
| | | else { |
| | |
| | | pItemErrors->addBoolItem(false, "ACKA"); |
| | | ISECS2Item* pItemErrors2 = pItemErrors->addItem(); |
| | | for (auto p : pjs) { |
| | | if (!p->issue().empty()) { |
| | | if (!p->issues().empty()) { |
| | | ISECS2Item* pItemErr = pItemErrors2->addItem(); |
| | | pItemErr->addU4Item(p->issue()[0].code, "ERRCODE"); |
| | | pItemErr->addItem(("<" + p->id() + ">" + p->issue()[0].text).c_str(), "ERRTEXT"); |
| | | pItemErr->addU4Item(p->issues()[0].code, "ERRCODE"); |
| | | pItemErr->addItem(("<" + p->id() + ">" + p->issues()[0].text).c_str(), "ERRTEXT"); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // éæ¾æé®é¢(æªæ·»å å°master)çå
å |
| | | for (auto p : pjs) { |
| | | if(!p->issue().empty()) delete p; |
| | | if(!p->issues().empty()) delete p; |
| | | } |
| | | pjs.clear(); |
| | | |
| | |
| | | #include <set> |
| | | #include "CCollectionEvent.h" |
| | | #include "ProcessJob.h" |
| | | #include "CControlJob.h" |
| | | |
| | | |
| | | #define EQCONSTANT_VALUE_MAX 64 |
| | |
| | | unsigned char PTN, |
| | | std::string& strErrorTxt)> CARRIERACTION; |
| | | typedef std::function<int(void* pFrom, std::vector<SERVO::CProcessJob*>& pjs)> PRJOBMULTICREATE; |
| | | typedef std::function<int(void* pFrom, SERVO::CControlJob& controlJob)> CONTROLJOBCREATE; |
| | | typedef struct _SECSListener |
| | | { |
| | | SECSEQOFFLINE onEQOffLine; |
| | |
| | | QUERYPPIDLIST onQueryPPIDList; |
| | | CARRIERACTION onCarrierAction; |
| | | PRJOBMULTICREATE onPRJobMultiCreate; |
| | | CONTROLJOBCREATE onControlJobCreate; |
| | | } SECSListener; |
| | | |
| | | |
| | |
| | | int replyPurgeSpooledData(IMessage* pRecv); |
| | | int replyQueryPPIDList(IMessage* pRecv); |
| | | int replyTerminalDisplay(IMessage* pRecv); |
| | | int replyCreateObj(IMessage* pRecv); |
| | | int replyPRJobMultiCreate(IMessage* pRecv); |
| | | |
| | | private: |
| | |
| | | |
| | | m_hsmsPassive.setVariableValue("PJQueued", vars); |
| | | m_hsmsPassive.requestEventReportSend_PJ_Queued(); |
| | | return nRet; |
| | | }; |
| | | listener.onControlJobCreate = [&](void* pFrom, SERVO::CControlJob& controlJob) -> int { |
| | | LOGI("<Model>onControlJobCreate %s %d", controlJob.id().c_str(), controlJob.priority()); |
| | | int nRet = m_master.setControlJob(controlJob); |
| | | return nRet; |
| | | }; |
| | | m_hsmsPassive.setListener(listener); |
| | |
| | | m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); |
| | | } |
| | | |
| | | const std::vector<CProcessJob::ValidationIssue>& CProcessJob::issue() |
| | | const std::vector<CProcessJob::ValidationIssue>& CProcessJob::issues() |
| | | { |
| | | return m_issues; |
| | | } |
| | |
| | | }; |
| | | // è¿åé®é¢æ¸
åï¼ç©º=éè¿ï¼ |
| | | bool validate(const IResourceView& rv); |
| | | const std::vector<ValidationIssue>& issue(); |
| | | const std::vector<ValidationIssue>& issues(); |
| | | |
| | | // ââ ç¶ææºï¼å¸¦å®å«ï¼ââ |
| | | bool queue(); // NoState -> Queued |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="CBaseDlg.h" /> |
| | | <ClInclude Include="CControlJob.h" /> |
| | | <ClInclude Include="CCustomCheckBox.h" /> |
| | | <ClInclude Include="CCollectionEvent.h" /> |
| | | <ClInclude Include="CEquipmentPage3.h" /> |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="CBaseDlg.cpp" /> |
| | | <ClCompile Include="CControlJob.cpp" /> |
| | | <ClCompile Include="CCustomCheckBox.cpp" /> |
| | | <ClCompile Include="CCollectionEvent.cpp" /> |
| | | <ClCompile Include="CEquipmentPage3.cpp" /> |
| | |
| | | <ClCompile Include="CPageReport.cpp" /> |
| | | <ClCompile Include="CPageCollectionEvent.cpp" /> |
| | | <ClCompile Include="ProcessJob.cpp" /> |
| | | <ClCompile Include="CControlJob.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | <ClInclude Include="CPageReport.h" /> |
| | | <ClInclude Include="CPageCollectionEvent.h" /> |
| | | <ClInclude Include="ProcessJob.h" /> |
| | | <ClInclude Include="CControlJob.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |