Merge branch 'clh' into liuyang
| | |
| | | #include "Log.h" |
| | | |
| | | |
| | | static unsigned int DATAID = 1; |
| | | |
| | | CHsmsActive::CHsmsActive() |
| | | { |
| | | m_listener = {}; |
| | |
| | | if (nStream == 5 && pHeader->function == 1) { |
| | | // S5F1 |
| | | replyAck(5, 2, pMessage->getHeader()->systemBytes, 0, _T("ACK0")); |
| | | } |
| | | else if (nStream == 6 && pHeader->function == 11) { |
| | | // S5F1 |
| | | replyAck(6, 12, pMessage->getHeader()->systemBytes, 0, _T("ACK0")); |
| | | } |
| | | }; |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsSelectedEquipmentStatusRequest(unsigned int SVID) |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | | int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 3, ++m_nSystemByte); |
| | | |
| | | pMessage->getBody()->addU4Item(SVID, "SVID"); |
| | | m_pActive->sendMessage(pMessage); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsActive::hsmsQueryPPIDList() |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | |
| | | return hsmsCarrierActionRequest(DATAID, "CarrierRelease", pszCarrierId, PTN); |
| | | } |
| | | |
| | | int CHsmsActive::hsmsPRJobMultiCreate(std::vector<SERVO::CProcessJob*>& pjs) |
| | | { |
| | | IMessage* pMessage = nullptr; |
| | | int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 16 | REPLY, 15, ++m_nSystemByte); |
| | | char szMF[32] = {14}; |
| | | pMessage->getBody()->addU4Item(++DATAID, "DATAID"); |
| | | auto itemPjs = pMessage->getBody()->addItem(); |
| | | for (auto pj : pjs) { |
| | | auto itemPj = itemPjs->addItem(); |
| | | itemPj->addItem(pj->id().c_str(), "PRJOBID"); |
| | | itemPj->addBinaryItem(szMF, 1, "MF"); |
| | | auto itemCarriers = itemPj->addItem(); |
| | | for (auto c : pj->carriers()) { |
| | | auto itemCarrier = itemCarriers->addItem(); |
| | | itemCarrier->addItem(c.carrierId.c_str(), "CARRIERID"); |
| | | auto itemSlots = itemCarrier->addItem(); |
| | | for (auto s : c.slots) { |
| | | itemSlots->addU1Item(s, "SLOTID"); |
| | | } |
| | | } |
| | | |
| | | auto recipeItems = itemPj->addItem(); |
| | | recipeItems->addU1Item(1, "PRRECIPEMETHOD"); |
| | | recipeItems->addItem(pj->recipeSpec().c_str(), "RCPSPEC"); |
| | | recipeItems->addItem(); |
| | | |
| | | itemPj->addBoolItem(false, "PRPROCESSSTART"); |
| | | itemPj->addItem(); |
| | | } |
| | | |
| | | m_pActive->sendMessage(pMessage); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | 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; |
| | |
| | | #include <map> |
| | | #include <set> |
| | | #include "CCollectionEvent.h" |
| | | #include "ProcessJob.h" |
| | | |
| | | |
| | | #define SVID_CJobSpace 5001 |
| | | #define SVID_PJobSpace 5002 |
| | | #define SVID_PJobQueued 5003 |
| | | |
| | | |
| | | typedef std::function<void(void* pFrom, ACTIVESTATE state)> STATECHANGED; |
| | |
| | | int hsmsTransmitSpooledData(); |
| | | int hsmsPurgeSpooledData(); |
| | | |
| | | // æ¥è¯¢åé |
| | | int hsmsSelectedEquipmentStatusRequest(unsigned int SVID); |
| | | |
| | | // æ¥è¯¢PPID List |
| | | int hsmsQueryPPIDList(); |
| | | |
| | |
| | | const char* pszCarrierId, |
| | | unsigned char PTN); |
| | | |
| | | // 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); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // CPJsDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "pch.h" |
| | | #include "EAPSimulator.h" |
| | | #include "CPJsDlg.h" |
| | | #include "afxdialogex.h" |
| | | |
| | | |
| | | // CPJsDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CPJsDlg, CDialogEx) |
| | | |
| | | CPJsDlg::CPJsDlg(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_PJS, pParent) |
| | | { |
| | | |
| | | } |
| | | |
| | | CPJsDlg::~CPJsDlg() |
| | | { |
| | | for (auto item : m_pjs) { |
| | | delete item; |
| | | } |
| | | m_pjs.clear(); |
| | | } |
| | | |
| | | void CPJsDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CPJsDlg, CDialogEx) |
| | | ON_BN_CLICKED(IDC_BUTTON_ADD, &CPJsDlg::OnBnClickedButtonAdd) |
| | | ON_BN_CLICKED(IDC_BUTTON_DELETE, &CPJsDlg::OnBnClickedButtonDelete) |
| | | ON_BN_CLICKED(IDC_BUTTON_SEND, &CPJsDlg::OnBnClickedButtonSend) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CPJsDlg æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | void CPJsDlg::OnBnClickedButtonAdd() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | } |
| | | |
| | | void CPJsDlg::OnBnClickedButtonDelete() |
| | | { |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1); |
| | | int nSel = pListCtrl->GetNextItem(-1, LVNI_SELECTED); |
| | | |
| | | if (nSel != -1) { |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)pListCtrl->GetItemData(nSel); |
| | | for (auto iter = m_pjs.begin(); iter != m_pjs.end(); ++iter) { |
| | | if (*iter == pj) { |
| | | delete (*iter); |
| | | m_pjs.erase(iter); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | pListCtrl->DeleteItem(nSel); |
| | | } |
| | | |
| | | void CPJsDlg::OnBnClickedButtonSend() |
| | | { |
| | | theApp.m_model.m_pHsmsActive->hsmsPRJobMultiCreate(m_pjs); |
| | | } |
| | | |
| | | BOOL CPJsDlg::OnInitDialog() |
| | | { |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | |
| | | // æ¥è¡¨æ§ä»¶ |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1); |
| | | DWORD dwStyle = pListCtrl->GetExtendedStyle(); |
| | | dwStyle |= LVS_EX_FULLROWSELECT; |
| | | dwStyle |= LVS_EX_GRIDLINES; |
| | | pListCtrl->SetExtendedStyle(dwStyle); |
| | | |
| | | HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1); |
| | | ListView_SetImageList(pListCtrl->GetSafeHwnd(), imageList, LVSIL_SMALL); |
| | | pListCtrl->InsertColumn(0, _T(""), LVCFMT_RIGHT, 0); |
| | | pListCtrl->InsertColumn(1, _T("PJ ID"), LVCFMT_LEFT, 100); |
| | | pListCtrl->InsertColumn(2, _T("Carrier1 & Slots"), LVCFMT_LEFT, 180); |
| | | pListCtrl->InsertColumn(3, _T("Carrier2 & Slots"), LVCFMT_LEFT, 180); |
| | | pListCtrl->InsertColumn(4, _T("Carrier3 & Slots"), LVCFMT_LEFT, 180); |
| | | pListCtrl->InsertColumn(5, _T("Carrier4 & Slots"), LVCFMT_LEFT, 180); |
| | | pListCtrl->InsertColumn(6, _T("PPID"), LVCFMT_LEFT, 180); |
| | | |
| | | |
| | | |
| | | // å建ç¨äºæµè¯çPJ |
| | | { |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob("PJ0001"); |
| | | std::vector<uint8_t> slots1{ 1, 2, 3 }; |
| | | pj->addCarrier("CID1001", slots1); |
| | | pj->setRecipe(SERVO::RecipeMethod::NoTuning, "P1001"); |
| | | m_pjs.push_back(pj); |
| | | } |
| | | { |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob("PJ0002"); |
| | | std::vector<uint8_t> slots1{ 1, 3 }; |
| | | pj->addCarrier("CID1002", slots1); |
| | | std::vector<uint8_t> slots2{ 1}; |
| | | pj->addCarrier("CID1003", slots2); |
| | | pj->setRecipe(SERVO::RecipeMethod::NoTuning, "R002"); |
| | | m_pjs.push_back(pj); |
| | | } |
| | | { |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob("PJ0003"); |
| | | std::vector<uint8_t> slots1{ 1, 2, 3, 5 }; |
| | | pj->addCarrier("CID1004", slots1); |
| | | pj->setRecipe(SERVO::RecipeMethod::NoTuning, "P1001"); |
| | | m_pjs.push_back(pj); |
| | | } |
| | | |
| | | // æ¾ç¤ºå°æ¥è¡¨ä¸ |
| | | for (auto item : m_pjs) { |
| | | AddPjToListCtrl(item); |
| | | } |
| | | |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | | } |
| | | |
| | | void CPJsDlg::AddPjToListCtrl(SERVO::CProcessJob* pj) |
| | | { |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1); |
| | | pListCtrl->InsertItem(0, _T("")); |
| | | pListCtrl->SetItemData(0, (DWORD_PTR)pj); |
| | | pListCtrl->SetItemText(0, 1, pj->id().c_str()); |
| | | pListCtrl->SetItemText(0, 6, pj->recipeSpec().c_str()); |
| | | |
| | | auto carries = pj->carriers(); |
| | | for (int i = 0; i < min(4, carries.size()); i++) { |
| | | pListCtrl->SetItemText(0, 2 + i, GetFormatString(carries[i])); ; |
| | | } |
| | | } |
| | | |
| | | CString CPJsDlg::GetFormatString(SERVO::CarrierSlotInfo& csi) |
| | | { |
| | | CString strRet; |
| | | strRet.Append(csi.carrierId.c_str()); |
| | | strRet.Append("<"); |
| | | int size = min(8, csi.slots.size()); |
| | | for (int i = 0; i < size; i++) { |
| | | strRet.Append(std::to_string(csi.slots[i]).c_str()); |
| | | if (i != size - 1) { |
| | | strRet.Append(","); |
| | | } |
| | | } |
| | | strRet.Append(">"); |
| | | |
| | | return strRet; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "ProcessJob.h" |
| | | #include <vector> |
| | | |
| | | |
| | | // CPJsDlg å¯¹è¯æ¡ |
| | | |
| | | class CPJsDlg : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CPJsDlg) |
| | | |
| | | public: |
| | | CPJsDlg(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CPJsDlg(); |
| | | void AddPjToListCtrl(SERVO::CProcessJob* pj); |
| | | CString GetFormatString(SERVO::CarrierSlotInfo& csi); |
| | | |
| | | private: |
| | | std::vector<SERVO::CProcessJob*> m_pjs; |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_PJS }; |
| | | #endif |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | public: |
| | | afx_msg void OnBnClickedButtonAdd(); |
| | | afx_msg void OnBnClickedButtonDelete(); |
| | | afx_msg void OnBnClickedButtonSend(); |
| | | virtual BOOL OnInitDialog(); |
| | | }; |
| | |
| | | <SDLCheck>true</SDLCheck> |
| | | <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> |
| | | <LanguageStandard>stdcpp17</LanguageStandard> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Windows</SubSystem> |
| | |
| | | <ClInclude Include="CModel.h" /> |
| | | <ClInclude Include="Common.h" /> |
| | | <ClInclude Include="Context.h" /> |
| | | <ClInclude Include="CPJsDlg.h" /> |
| | | <ClInclude Include="CReport.h" /> |
| | | <ClInclude Include="CTerminalDisplayDlg.h" /> |
| | | <ClInclude Include="CVariable.h" /> |
| | |
| | | <ClInclude Include="Log.h" /> |
| | | <ClInclude Include="LogEdit.h" /> |
| | | <ClInclude Include="pch.h" /> |
| | | <ClInclude Include="ProcessJob.h" /> |
| | | <ClInclude Include="Resource.h" /> |
| | | <ClInclude Include="targetver.h" /> |
| | | </ItemGroup> |
| | |
| | | <ClCompile Include="CLinkReportDlg.cpp" /> |
| | | <ClCompile Include="CModel.cpp" /> |
| | | <ClCompile Include="Context.cpp" /> |
| | | <ClCompile Include="CPJsDlg.cpp" /> |
| | | <ClCompile Include="CReport.cpp" /> |
| | | <ClCompile Include="CTerminalDisplayDlg.cpp" /> |
| | | <ClCompile Include="CVariable.cpp" /> |
| | |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> |
| | | </ClCompile> |
| | | <ClCompile Include="ProcessJob.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="EAPSimulator.rc" /> |
| | |
| | | <ClInclude Include="CLinkReportDetailDlg.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="CPJsDlg.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="ProcessJob.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="EAPSimulator.cpp"> |
| | |
| | | <ClCompile Include="CLinkReportDetailDlg.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="CPJsDlg.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="ProcessJob.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="EAPSimulator.rc"> |
| | |
| | | #include "CEDEventReportDlg.h" |
| | | #include "CDefineReportsDlg.h" |
| | | #include "CLinkReportDlg.h" |
| | | #include "CPJsDlg.h" |
| | | |
| | | |
| | | #ifdef _DEBUG |
| | |
| | | ON_BN_CLICKED(IDC_BUTTON_QUERY_PPID_LIST, &CEAPSimulatorDlg::OnBnClickedButtonQueryPpidList) |
| | | ON_BN_CLICKED(IDC_BUTTON_PROCEED_WITH_CARRIER, &CEAPSimulatorDlg::OnBnClickedButtonProceedWithCarrier) |
| | | ON_BN_CLICKED(IDC_BUTTON_CARRIER_RELEASE, &CEAPSimulatorDlg::OnBnClickedButtonCarrierRelease) |
| | | 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_PPID_LIST)->EnableWindow(enabled); |
| | | GetDlgItem(IDC_BUTTON_PROCEED_WITH_CARRIER)->EnableWindow(enabled); |
| | | GetDlgItem(IDC_BUTTON_CARRIER_RELEASE)->EnableWindow(enabled); |
| | | 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() |
| | |
| | | theApp.m_model.m_pHsmsActive->hsmsPurgeSpooledData(); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonQueryCjSpace() |
| | | { |
| | | theApp.m_model.m_pHsmsActive->hsmsSelectedEquipmentStatusRequest(SVID_CJobSpace); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonQueryPjSpace() |
| | | { |
| | | theApp.m_model.m_pHsmsActive->hsmsSelectedEquipmentStatusRequest(SVID_PJobQueued); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonQueryPpidList() |
| | | { |
| | | theApp.m_model.m_pHsmsActive->hsmsQueryPPIDList(); |
| | |
| | | { |
| | | theApp.m_model.m_pHsmsActive->hsmsCarrierRelease(DATAID++, "CSX 52078", 2); |
| | | } |
| | | |
| | | void CEAPSimulatorDlg::OnBnClickedButtonCreatePj() |
| | | { |
| | | 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 OnBnClickedButtonQueryPpidList(); |
| | | afx_msg void OnBnClickedButtonProceedWithCarrier(); |
| | | afx_msg void OnBnClickedButtonCarrierRelease(); |
| | | afx_msg void OnBnClickedButtonQueryCjSpace(); |
| | | afx_msg void OnBnClickedButtonQueryPjSpace(); |
| | | afx_msg void OnBnClickedButtonCreatePj(); |
| | | afx_msg void OnBnClickedButtonCreateCj(); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "pch.h" |
| | | #include "ProcessJob.h" |
| | | #include <cctype> |
| | | |
| | | namespace SERVO { |
| | | 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; |
| | | } |
| | | |
| | | CProcessJob::CProcessJob(std::string pjId) |
| | | : m_pjId(trimCopy(pjId)) |
| | | { |
| | | clampString(m_pjId, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::setParentCjId(std::string cjId) { |
| | | m_parentCjId = trimCopy(cjId); |
| | | clampString(m_parentCjId, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::setRecipe(RecipeMethod method, std::string spec) { |
| | | m_recipeMethod = method; |
| | | m_recipeSpec = trimCopy(spec); |
| | | clampString(m_recipeSpec, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::addParam(std::string name, std::string value) { |
| | | name = trimCopy(name); |
| | | value = trimCopy(value); |
| | | clampString(name, MAX_PARAM_K); |
| | | clampString(value, MAX_PARAM_V); |
| | | m_params.push_back({ std::move(name), std::move(value) }); |
| | | } |
| | | |
| | | void CProcessJob::setParams(std::vector<PJParam> params) { |
| | | m_params.clear(); |
| | | m_params.reserve(params.size()); |
| | | for (auto& p : params) addParam(std::move(p.name), std::move(p.value)); |
| | | } |
| | | |
| | | void CProcessJob::addPauseEvent(uint32_t ceid) { |
| | | if (ceid) m_pauseEvents.push_back(ceid); |
| | | std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); |
| | | m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); |
| | | } |
| | | |
| | | void CProcessJob::setPauseEvents(std::vector<uint32_t> ceids) { |
| | | m_pauseEvents = std::move(ceids); |
| | | std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); |
| | | m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); |
| | | } |
| | | |
| | | std::vector<CProcessJob::ValidationIssue> |
| | | CProcessJob::validate(const IResourceView& rv) const |
| | | { |
| | | std::vector<ValidationIssue> issues; |
| | | |
| | | // 让 add åæ¶æ¯æ const char* å std::string |
| | | auto add = [&](uint32_t code, std::string msg) { |
| | | issues.push_back({ code, std::move(msg) }); |
| | | }; |
| | | |
| | | // ââ åºæ¬ / æ è¯ ââ |
| | | if (m_pjId.empty()) add(1001, "PJID empty"); |
| | | if (!asciiPrintable(m_pjId)) add(1002, "PJID has non-printable chars"); |
| | | |
| | | if (m_parentCjId.empty()) add(1010, "Parent CJID empty"); |
| | | |
| | | // ââ é
æ¹ï¼RCPSPEC / PPIDï¼ââ |
| | | if (m_recipeSpec.empty()) add(1020, "Recipe spec (PPID) empty"); |
| | | else if (!rv.recipeExists(m_recipeSpec)) { |
| | | add(1021, "PPID not found: " + m_recipeSpec); |
| | | } |
| | | |
| | | // ââ é
æ¹æ¹æ³ vs åæ° ââ 1=NoTuning ç¦æ¢å¸¦åæ°ï¼2=WithTuning å
许/å¯é |
| | | if (m_recipeMethod == RecipeMethod::NoTuning && !m_params.empty()) { |
| | | add(1022, "Params not allowed when PRRECIPEMETHOD=1 (NoTuning)"); |
| | | } |
| | | |
| | | // ââ ç©æéæ©æ ¡éª ââï¼äºéä¸ï¼Carrier+Slots æ MIDsï¼ä¸¤è
é½ä¸å¡«åéè¯¯ï¼ |
| | | const bool hasCarrierSlots = !m_carriers.empty(); |
| | | if (hasCarrierSlots) { |
| | | // {L:n { CARRIERID {L:j SLOTID} }} |
| | | for (const auto& cs : m_carriers) { |
| | | if (cs.carrierId.empty()) { |
| | | add(1030, "CarrierID empty"); |
| | | continue; |
| | | } |
| | | if (!rv.carrierPresent(cs.carrierId)) { |
| | | add(1031, "Carrier not present: " + cs.carrierId); |
| | | } |
| | | if (cs.slots.empty()) { |
| | | add(1032, "No slots specified for carrier: " + cs.carrierId); |
| | | } |
| | | for (auto s : cs.slots) { |
| | | if (s == 0) { |
| | | add(1033, "Slot 0 is invalid for carrier: " + cs.carrierId); |
| | | continue; |
| | | } |
| | | if (!rv.slotUsable(cs.carrierId, s)) { |
| | | add(1034, "Slot unusable: carrier=" + cs.carrierId + " slot=" + std::to_string(s)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | add(1035, "No material selection provided (neither Carrier/Slots nor MIDs)"); |
| | | } |
| | | |
| | | // ââ æåäºä»¶ï¼PRPAUSEEVENTID å表ï¼ââ |
| | | for (auto ceid : m_pauseEvents) { |
| | | if (!rv.ceidDefined(ceid)) { |
| | | add(1050, "Pause CEID unknown: " + std::to_string(ceid)); |
| | | } |
| | | } |
| | | |
| | | return issues; |
| | | } |
| | | |
| | | // ââ ç¶ææº ââ |
| | | // è§åå¯æä½ ä»¬åè®®å¾®è° |
| | | bool CProcessJob::queue() { |
| | | if (m_state != PJState::NoState) return false; |
| | | markQueued(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::enterSettingUp() { |
| | | if (m_state != PJState::Queued) return false; |
| | | m_state = PJState::SettingUp; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::start() { |
| | | if (m_state != PJState::Queued && m_state != PJState::SettingUp && m_state != PJState::Paused) |
| | | return false; |
| | | if (!m_tStart.has_value()) markStart(); |
| | | m_state = PJState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::pause() { |
| | | if (m_state != PJState::InProcess) return false; |
| | | m_state = PJState::Paused; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::resume() { |
| | | if (m_state != PJState::Paused) return false; |
| | | m_state = PJState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::complete() { |
| | | if (m_state != PJState::InProcess && m_state != PJState::Paused) return false; |
| | | m_state = PJState::Completed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::abort() { |
| | | if (m_state == PJState::Completed || m_state == PJState::Aborted || m_state == PJState::Failed) |
| | | return false; |
| | | m_state = PJState::Aborted; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::fail(std::string reason) { |
| | | m_failReason = trimCopy(reason); |
| | | clampString(m_failReason, 128); |
| | | m_state = PJState::Failed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | // ââ æ¶é´æ³ & å·¥å
· ââ |
| | | void CProcessJob::markQueued() { |
| | | m_state = PJState::Queued; |
| | | m_tQueued = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::markStart() { |
| | | m_tStart = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::markEnd() { |
| | | m_tEnd = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::clampString(std::string& s, size_t maxLen) { |
| | | if (s.size() > maxLen) s.resize(maxLen); |
| | | } |
| | | |
| | | bool CProcessJob::asciiPrintable(const std::string& s) { |
| | | return std::all_of(s.begin(), s.end(), [](unsigned char c) { |
| | | return c >= 0x20 && c <= 0x7E; |
| | | }); |
| | | } |
| | | |
| | | void CProcessJob::setCarriers(std::vector<CarrierSlotInfo> carriers) |
| | | { |
| | | // ç»ä¸éè¿ addCarrier åè§èåï¼å»ç©ºç½ãæªæãå»éãåå¹¶å carrierï¼ |
| | | m_carriers.clear(); |
| | | m_carriers.reserve(carriers.size()); |
| | | for (auto& cs : carriers) { |
| | | addCarrier(std::move(cs.carrierId), std::move(cs.slots)); |
| | | } |
| | | } |
| | | |
| | | void CProcessJob::addCarrier(std::string carrierId, std::vector<uint8_t> slots) |
| | | { |
| | | // 1) è§èå carrierIdï¼å»ç©ºç½ + é¿åº¦éå¶ |
| | | carrierId = trimCopy(std::move(carrierId)); |
| | | clampString(carrierId, MAX_ID_LEN); |
| | | if (carrierId.empty()) { |
| | | // 空 ID ç´æ¥å¿½ç¥ï¼ä¹å¯ä»¥éæ©æå¼å¸¸/è®°å½æ¥å¿ï¼çä½ é¡¹ç®é£æ ¼ï¼ |
| | | return; |
| | | } |
| | | |
| | | // 2) è§èå slotsï¼å» 0ãæåºãå»é |
| | | // 注ï¼SLOTID æ 1..Nï¼0 è§ä¸ºéæ³/å ä½ |
| | | slots.erase(std::remove(slots.begin(), slots.end(), 0), slots.end()); |
| | | std::sort(slots.begin(), slots.end()); |
| | | slots.erase(std::unique(slots.begin(), slots.end()), slots.end()); |
| | | if (slots.empty()) { |
| | | // æ²¡æææå¡ä½å°±ä¸è¿½å |
| | | return; |
| | | } |
| | | |
| | | // 3) 妿已åå¨ååè½½å
·ï¼ååå¹¶ slot å表 |
| | | auto it = std::find_if(m_carriers.begin(), m_carriers.end(), |
| | | [&](const CarrierSlotInfo& cs) { return cs.carrierId == carrierId; }); |
| | | |
| | | if (it != m_carriers.end()) { |
| | | // åå¹¶ |
| | | it->slots.insert(it->slots.end(), slots.begin(), slots.end()); |
| | | std::sort(it->slots.begin(), it->slots.end()); |
| | | it->slots.erase(std::unique(it->slots.begin(), it->slots.end()), it->slots.end()); |
| | | } |
| | | else { |
| | | // æ°å¢ |
| | | CarrierSlotInfo cs; |
| | | cs.carrierId = std::move(carrierId); |
| | | cs.slots = std::move(slots); |
| | | m_carriers.emplace_back(std::move(cs)); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <string> |
| | | #include <vector> |
| | | #include <unordered_map> |
| | | #include <unordered_set> |
| | | #include <algorithm> |
| | | #include <cstdint> |
| | | #include <chrono> |
| | | #include <optional> |
| | | |
| | | namespace SERVO { |
| | | /// PJ çå½å¨æï¼è´´è¿ E40 常è§ç¶æï¼ |
| | | enum class PJState : uint8_t { |
| | | NoState = 0, |
| | | Queued, |
| | | SettingUp, |
| | | InProcess, |
| | | Paused, |
| | | Aborting, |
| | | Completed, |
| | | Aborted, |
| | | Failed |
| | | }; |
| | | |
| | | /// é
æ¹æå®æ¹å¼ï¼å¯¹åº S16F15 é PRRECIPEMETHODï¼ |
| | | enum class RecipeMethod : uint8_t { |
| | | NoTuning = 1, // 1 - recipe without variable tuning |
| | | WithTuning = 2 // 2 - recipe with variable tuning |
| | | }; |
| | | |
| | | /// å¯å¨çç¥ï¼å¯¹åº S16F15 é PRPROCESSSTARTï¼ |
| | | enum class StartPolicy : uint8_t { |
| | | Queued = 0, // 建ç«åæé |
| | | AutoStart = 1 // æ¡ä»¶æ»¡è¶³åèªå¨å¯å¨ |
| | | }; |
| | | |
| | | /** é
æ¹åæ°å¯¹ï¼S16F15 ä¸ RCPPARNM / RCPPARVALï¼ */ |
| | | struct PJParam { |
| | | std::string name; // RCPPARNM |
| | | std::string value; // RCPPARVAL |
| | | }; |
| | | |
| | | /** |
| | | {L:2 |
| | | CARRIERID |
| | | {L:j |
| | | SLOTID |
| | | } |
| | | } |
| | | */ |
| | | struct CarrierSlotInfo { |
| | | std::string carrierId; // CARRIERID |
| | | std::vector<uint8_t> slots; // SLOTID[] |
| | | }; |
| | | |
| | | /// ç®åèµæºè§å¾æ¥å£ï¼ä¾ Validate() æ¥è¯¢ï¼ç±è®¾å¤ç«¯å®ç°è
å¨å¤é¨æä¾ï¼ |
| | | struct IResourceView { |
| | | virtual ~IResourceView() = default; |
| | | virtual bool recipeExists(const std::string& ppid) const = 0; |
| | | virtual bool carrierPresent(const std::string& carrierId) const = 0; |
| | | virtual bool slotUsable(const std::string& carrierId, uint16_t slot) const = 0; |
| | | virtual bool ceidDefined(uint32_t ceid) const = 0; |
| | | // ä½ ä¹å¯ä»¥æ©å±ï¼portç¶æãå ç¨æ
åµãCJ/PJ空é´ç |
| | | }; |
| | | |
| | | /// PJ 主类 |
| | | /** |
| | | * ProcessJob ââ ä¸ S16F15ï¼PRJobMultiCreateï¼å段ä¸ä¸å¯¹åºçæ¿è½½ç±» |
| | | * |
| | | * S16F15 ç»æï¼æ ¸å¿èéï¼ï¼ |
| | | * {L:6 |
| | | * PRJOBID -> m_pjId |
| | | * MF -> m_mf |
| | | * {L:n { CARRIERID {L:j SLOTID} } } |
| | | * {L:3 |
| | | * PRRECIPEMETHOD -> m_recipeType |
| | | * RCPSPECï¼PPIDï¼ -> m_recipeSpec |
| | | * {L:m { RCPPARNM RCPPARVAL }} -> m_params |
| | | * } |
| | | * PRPROCESSSTART -> m_startPolicy |
| | | * {L:k PRPAUSEEVENTID} -> m_pauseEvents |
| | | * } |
| | | */ |
| | | class CProcessJob { |
| | | public: |
| | | // ââ æé / åºæ¬è®¾ç½® ââ |
| | | explicit CProcessJob(std::string pjId); |
| | | |
| | | const std::string& id() const noexcept { return m_pjId; } |
| | | const std::string& parentCjId() const noexcept { return m_parentCjId; } |
| | | PJState state() const noexcept { return m_state; } |
| | | StartPolicy startPolicy() const noexcept { return m_startPolicy; } |
| | | RecipeMethod recipeMethod() const noexcept { return m_recipeMethod; } |
| | | const std::string& recipeSpec() const noexcept { return m_recipeSpec; } // PPID æ Spec |
| | | |
| | | // ç»å®ç¶ CJ |
| | | void setParentCjId(std::string cjId); |
| | | |
| | | // é
æ¹ |
| | | void setRecipe(RecipeMethod method, std::string spec); |
| | | |
| | | // å¯å¨çç¥ |
| | | void setStartPolicy(StartPolicy sp) { m_startPolicy = sp; } |
| | | |
| | | // åæ° |
| | | void addParam(std::string name, std::string value); |
| | | void setParams(std::vector<PJParam> params); |
| | | |
| | | // æåäºä»¶ |
| | | void addPauseEvent(uint32_t ceid); |
| | | void setPauseEvents(std::vector<uint32_t> ceids); |
| | | |
| | | // ââ æ ¡éª ââ |
| | | struct ValidationIssue { |
| | | uint32_t code; // èªå®ä¹é误ç |
| | | std::string text; // ææ¬æè¿° |
| | | }; |
| | | // è¿åé®é¢æ¸
åï¼ç©º=éè¿ï¼ |
| | | std::vector<ValidationIssue> validate(const IResourceView& rv) const; |
| | | |
| | | // ââ ç¶ææºï¼å¸¦å®å«ï¼ââ |
| | | bool queue(); // NoState -> Queued |
| | | bool start(); // Queued/SettingUp -> InProcess |
| | | bool enterSettingUp(); // Queued -> SettingUp |
| | | bool pause(); // InProcess -> Paused |
| | | bool resume(); // Paused -> InProcess |
| | | bool complete(); // InProcess -> Completed |
| | | bool abort(); // Any (æªç»æ) -> Aborted |
| | | bool fail(std::string reason); // ä»»ææ -> Failedï¼è®°å½å¤±è´¥åå ï¼ |
| | | |
| | | // ââ 访é®å¨ï¼ç¨äºä¸æ¥/æ¥è¯¢ï¼ââ |
| | | const std::vector<PJParam>& params() const noexcept { return m_params; } |
| | | const std::vector<uint32_t>& pauseEvents() const noexcept { return m_pauseEvents; } |
| | | 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; } |
| | | |
| | | // é¿åº¦éå¶å·¥å
·ï¼å¯å¨éææ¶ç»ä¸çç¥ï¼ |
| | | static void clampString(std::string& s, size_t maxLen); |
| | | static bool asciiPrintable(const std::string& s); |
| | | |
| | | // æ¸
空并æ´ä½è®¾ç½® |
| | | void setCarriers(std::vector<CarrierSlotInfo> carriers); |
| | | |
| | | // 追å ä¸ä¸ªè½½å
· |
| | | void addCarrier(std::string carrierId, std::vector<uint8_t> slots); |
| | | |
| | | // 访é®å¨ |
| | | const std::vector<CarrierSlotInfo>& carriers() const noexcept { return m_carriers; } |
| | | |
| | | // å¤å®æ¯å¦âæè½½å
·/å¡ä½âæ¹å¼ |
| | | bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); } |
| | | |
| | | |
| | | private: |
| | | // å
é¨ç¶æè½¬ç§»å¸®å© |
| | | void markQueued(); |
| | | void markStart(); |
| | | void markEnd(); |
| | | |
| | | private: |
| | | // æ è¯ |
| | | std::string m_pjId; |
| | | std::string m_parentCjId; |
| | | |
| | | // é
æ¹ |
| | | RecipeMethod m_recipeMethod{ RecipeMethod::NoTuning }; |
| | | std::string m_recipeSpec; // PPID / Spec |
| | | |
| | | // ç©æ |
| | | static constexpr uint8_t MATERIAL_FORMAT = 14; // substrate |
| | | std::vector<CarrierSlotInfo> m_carriers; // {L:n { CARRIERID {L:j SLOTID} }} |
| | | |
| | | // åæ° / æåäºä»¶ |
| | | std::vector<PJParam> m_params; |
| | | std::vector<uint32_t> m_pauseEvents; |
| | | |
| | | // ç¶æ & è®°å½ |
| | | StartPolicy m_startPolicy{ StartPolicy::Queued }; // 0=Queued, 1=AutoStart |
| | | PJState m_state{ PJState::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; // PJID/ CJID/ CarrierID/ MID/ PPID |
| | | static constexpr size_t MAX_PARAM_K = 32; // åæ°å |
| | | static constexpr size_t MAX_PARAM_V = 64; // åæ°å¼ |
| | | }; |
| | | } |
| | | |
| | | |
| | |
| | | #define IDD_DIALOG_ADD_IDS 135 |
| | | #define IDD_DIALOG_LINK_REPORT 137 |
| | | #define IDD_DIALOG_LINK_REPORT_DETAIL 139 |
| | | #define IDD_DIALOG_PJS 141 |
| | | #define IDC_EDIT_LOG 1000 |
| | | #define IDC_EDIT_IP 1001 |
| | | #define IDC_EDIT_PORT 1002 |
| | |
| | | #define IDC_EDIT_CE_NAME 1031 |
| | | #define IDC_BUTTON_QUERY_PPID_LIST 1032 |
| | | #define IDC_EDIT_CE_RPTID 1033 |
| | | #define IDC_BUTTON_PROCEED_WITH_CARRIER 1033 |
| | | #define IDC_BUTTON_TRANSMIT_SPOOLED_DATA 1034 |
| | | #define IDC_BUTTON_PROCEED_WITH_CARRIER2 1035 |
| | | #define IDC_BUTTON_CARRIER_RELEASE 1035 |
| | | #define IDC_BUTTON_PROCEED_WITH_CARRIER 1034 |
| | | #define IDC_BUTTON_TRANSMIT_SPOOLED_DATA 1035 |
| | | #define IDC_BUTTON_CARRIER_RELEASE 1036 |
| | | #define IDC_BUTTON_QUERY_CJ_SPACE 1037 |
| | | #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 |
| | | // |
| | | #ifdef APSTUDIO_INVOKED |
| | | #ifndef APSTUDIO_READONLY_SYMBOLS |
| | | #define _APS_NEXT_RESOURCE_VALUE 141 |
| | | #define _APS_NEXT_RESOURCE_VALUE 143 |
| | | #define _APS_NEXT_COMMAND_VALUE 32771 |
| | | #define _APS_NEXT_CONTROL_VALUE 1035 |
| | | #define _APS_NEXT_CONTROL_VALUE 1042 |
| | | #define _APS_NEXT_SYMED_VALUE 101 |
| | | #endif |
| | | #endif |
| | |
| | | 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> |
| | | #include "SerializeUtil.h" |
| | | |
| | | 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() |
| | | { |
| | | |
| | | } |
| | | |
| | | 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; |
| | | }); |
| | | } |
| | | |
| | | void CControlJob::serialize(std::ostream& os) const { |
| | | write_pod(os, CJ_MAGIC); |
| | | write_pod(os, CJ_VERSION); |
| | | |
| | | // æ è¯/ä¼å
级/ç¶æ/失败åå |
| | | write_string(os, id()); // æ m_cjId |
| | | write_pod<uint8_t>(os, priority()); // æ m_priority |
| | | write_pod<uint8_t>(os, static_cast<uint8_t>(state())); // æ m_state |
| | | write_string(os, failReason()); // æ m_failReason |
| | | |
| | | // æ¶é´æ³ |
| | | write_opt_time(os, tQueued()); |
| | | write_opt_time(os, tStart()); |
| | | write_opt_time(os, tEnd()); |
| | | |
| | | // å
³è PJ å表 |
| | | write_vec_str(os, pjIds()); // æ m_pjIds |
| | | } |
| | | |
| | | bool CControlJob::deserialize(std::istream& is, CControlJob& out, std::string* err) { |
| | | auto fail = [&](const char* msg) { if (err) *err = msg; return false; }; |
| | | |
| | | uint32_t magic = 0; if (!read_pod(is, magic)) return fail("read CJ magic"); |
| | | if (magic != CJ_MAGIC) return fail("bad CJ magic"); |
| | | |
| | | uint16_t ver = 0; if (!read_pod(is, ver)) return fail("read CJ version"); |
| | | if (ver != CJ_VERSION) return fail("unsupported CJ version"); |
| | | |
| | | std::string cjId; |
| | | if (!read_string(is, cjId)) return fail("read CJID"); |
| | | |
| | | uint8_t prio = 0; |
| | | if (!read_pod(is, prio)) return fail("read Priority"); |
| | | |
| | | uint8_t st = 0; |
| | | if (!read_pod(is, st)) return fail("read State"); |
| | | |
| | | std::string failText; |
| | | if (!read_string(is, failText)) return fail("read failReason"); |
| | | |
| | | std::optional<std::chrono::system_clock::time_point> tQ, tS, tE; |
| | | if (!read_opt_time(is, tQ)) return fail("read tQueued"); |
| | | if (!read_opt_time(is, tS)) return fail("read tStart"); |
| | | if (!read_opt_time(is, tE)) return fail("read tEnd"); |
| | | |
| | | std::vector<std::string> pjIds; |
| | | if (!read_vec_str(is, pjIds)) return fail("read PJIDs"); |
| | | |
| | | // ââ åå对象ï¼ç´æ¥æ¹æåï¼æéè¿ setterï¼ââ |
| | | // è¥ä½ æ setterï¼out.setId(...)/setPriority(...)/setState(...)/setFailReason(...) |
| | | out = CControlJob(cjId); |
| | | out.setPriority(prio); |
| | | |
| | | // ç´æ¥æ¢å¤å
é¨ç¶æï¼è¥ä½ è¦æ±èµ°ç¶ææºï¼å¯å¨è¿éæåæ³è¿æ¸¡è°ç¨ queue()/start()/...ï¼ |
| | | // ç®åï¼ç´æ¥èµå¼ï¼ä½ å¨ CControlJob.cpp å
é¨ï¼å¯è®¿é®ç§ææåï¼ |
| | | struct Access : CControlJob { |
| | | using CControlJob::m_state; |
| | | using CControlJob::m_failReason; |
| | | using CControlJob::m_tQueued; |
| | | using CControlJob::m_tStart; |
| | | using CControlJob::m_tEnd; |
| | | using CControlJob::m_pjIds; |
| | | }; |
| | | auto& a = reinterpret_cast<Access&>(out); |
| | | a.m_state = static_cast<CJState>(st); |
| | | a.m_failReason = std::move(failText); |
| | | a.m_tQueued = std::move(tQ); |
| | | a.m_tStart = std::move(tS); |
| | | a.m_tEnd = std::move(tE); |
| | | a.m_pjIds = std::move(pjIds); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | std::string CControlJob::getStateText() |
| | | { |
| | | switch (m_state) |
| | | { |
| | | case SERVO::CJState::NoState: |
| | | return "NoState"; |
| | | break; |
| | | case SERVO::CJState::Queued: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::CJState::Executing: |
| | | return "Executing"; |
| | | break; |
| | | case SERVO::CJState::Paused: |
| | | return "Paused"; |
| | | break; |
| | | case SERVO::CJState::Completed: |
| | | return "Completed"; |
| | | break; |
| | | case SERVO::CJState::Aborted: |
| | | return "Aborted"; |
| | | break; |
| | | case SERVO::CJState::Failed: |
| | | return "Failed"; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #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: |
| | | CControlJob(); |
| | | 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; } |
| | | std::string getStateText(); |
| | | |
| | | // ââ 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(); } |
| | | const std::vector<CProcessJob*>& getPjs() { return m_pjs; }; |
| | | |
| | | // ââ æ ¡éª ââ // |
| | | 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); |
| | | |
| | | static constexpr uint32_t CJ_MAGIC = 0x434A5031; // "CJP1" |
| | | static constexpr uint16_t CJ_VERSION = 0x0001; |
| | | |
| | | void serialize(std::ostream& os) const; |
| | | static bool deserialize(std::istream& is, CControlJob& out, std::string* err = nullptr); |
| | | |
| | | private: |
| | | void markQueued(); |
| | | void markStart(); |
| | | void markEnd(); |
| | | |
| | | protected: |
| | | // ââ æ è¯ & é
ç½® ââ // |
| | | 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; |
| | | }; |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // CControlJobDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.h" |
| | | #include "CControlJobDlg.h" |
| | | #include "afxdialogex.h" |
| | | |
| | | |
| | | // CControlJobDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CControlJobDlg, CDialogEx) |
| | | |
| | | CControlJobDlg::CControlJobDlg(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_CONTROL_JOB, pParent) |
| | | { |
| | | m_pControlJob = nullptr; |
| | | } |
| | | |
| | | CControlJobDlg::~CControlJobDlg() |
| | | { |
| | | } |
| | | |
| | | void CControlJobDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_LIST1, m_listCtrl); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CControlJobDlg, CDialogEx) |
| | | ON_WM_SIZE() |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | void CControlJobDlg::SetControlJob(SERVO::CControlJob* pControlJob) |
| | | { |
| | | m_pControlJob = pControlJob; |
| | | } |
| | | |
| | | // CControlJobDlg æ¶æ¯å¤çç¨åº |
| | | BOOL CControlJobDlg::OnInitDialog() |
| | | { |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | |
| | | // labelåä½ |
| | | LOGFONT lf{}; |
| | | GetFont()->GetLogFont(&lf); |
| | | lf.lfHeight = -20; |
| | | lf.lfWeight = FW_BOLD; |
| | | _tcscpy_s(lf.lfFaceName, _T("Arial")); |
| | | m_fontNoJob.CreateFontIndirect(&lf); |
| | | GetDlgItem(IDC_LABEL_NO_JOB)->SetFont(&m_fontNoJob); |
| | | |
| | | |
| | | // å表æ§ä»¶ |
| | | HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1); |
| | | ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL); |
| | | m_listCtrl.ModifyStyle(0, LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS); |
| | | m_listCtrl.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 180); |
| | | m_listCtrl.InsertColumn(1, _T("ç±»å"), LVCFMT_LEFT, 120); |
| | | m_listCtrl.InsertColumn(2, _T("ç¶æ"), LVCFMT_LEFT, 120); |
| | | m_listCtrl.InsertColumn(3, _T("é
æ¹"), LVCFMT_LEFT, 120); |
| | | m_listCtrl.InsertColumn(4, _T("Port / Carrier / Slot"), LVCFMT_LEFT, 180); |
| | | m_listCtrl.InsertColumn(5, _T("æè¿°"), LVCFMT_LEFT, 220); |
| | | |
| | | |
| | | // æ§ä»¶ç¶æ |
| | | Resize(); |
| | | ShowGroup1(m_pControlJob == nullptr); |
| | | ShowGroup2(m_pControlJob != nullptr); |
| | | LoadData(); |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | | } |
| | | |
| | | void CControlJobDlg::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | if (GetDlgItem(IDC_LIST1) == nullptr) return; |
| | | Resize(); |
| | | } |
| | | |
| | | void CControlJobDlg::Resize() |
| | | { |
| | | CRect rcClient, rcItem; |
| | | CWnd* pItem; |
| | | |
| | | GetClientRect(rcClient); |
| | | |
| | | |
| | | // å
³éæé® |
| | | int y = rcClient.bottom - 12; |
| | | pItem = GetDlgItem(IDCANCEL); |
| | | pItem->GetClientRect(&rcItem); |
| | | pItem->MoveWindow(rcClient.right - 12 - rcItem.Width(), |
| | | y - rcItem.Height(), |
| | | rcItem.Width(), rcItem.Height()); |
| | | y -= rcItem.Height(); |
| | | y -= 12; |
| | | |
| | | |
| | | // 线 |
| | | pItem = GetDlgItem(IDC_LINE1); |
| | | pItem->MoveWindow(12, y, rcClient.Width() - 24, 2); |
| | | y -= 2; |
| | | |
| | | |
| | | // Label |
| | | pItem = GetDlgItem(IDC_LABEL_NO_JOB); |
| | | pItem->GetClientRect(&rcItem); |
| | | pItem->MoveWindow((rcClient.Width() - rcItem.Width()) / 2, |
| | | (y - rcItem.Height()) / 2, |
| | | rcItem.Width(), rcItem.Height()); |
| | | |
| | | |
| | | // ListCtrl |
| | | pItem = GetDlgItem(IDC_LIST1); |
| | | pItem->MoveWindow(12, 12, rcClient.Width() - 24, y - 12); |
| | | } |
| | | |
| | | void CControlJobDlg::ShowGroup1(BOOL bShow) |
| | | { |
| | | GetDlgItem(IDC_LABEL_NO_JOB)->ShowWindow(bShow ? SW_SHOW : SW_HIDE); |
| | | GetDlgItem(IDC_LINE1)->ShowWindow(bShow ? SW_SHOW : SW_HIDE); |
| | | } |
| | | |
| | | void CControlJobDlg::ShowGroup2(BOOL bShow) |
| | | { |
| | | GetDlgItem(IDC_LIST1)->ShowWindow(bShow ? SW_SHOW : SW_HIDE); |
| | | } |
| | | |
| | | void CControlJobDlg::LoadData() |
| | | { |
| | | m_listCtrl.DeleteAllItems(); |
| | | |
| | | if (m_pControlJob != nullptr) { |
| | | auto* root1 = m_listCtrl.InsertRoot({ m_pControlJob->id().c_str(), _T("ControlJob"), |
| | | m_pControlJob->getStateText().c_str(), _T("") }); |
| | | auto pjs = m_pControlJob->getPjs(); |
| | | for (auto pj : pjs) { |
| | | auto* root2 = m_listCtrl.InsertChild(root1, {pj->id().c_str(), _T("ProcessJob"), |
| | | pj->getStateText().c_str(), pj->recipeSpec().c_str(), _T(""), _T(""), _T("") }); |
| | | auto cs = pj->carriers(); |
| | | for (auto c : cs) { |
| | | for (auto g : c.contexts) { |
| | | SERVO::CGlass* pGlass = (SERVO::CGlass*)g; |
| | | if (pGlass != nullptr) { |
| | | int port, slot; |
| | | pGlass->getOrginPort(port, slot); |
| | | std::string carrier = c.carrierId + " / Port" + std::to_string(port + 1) + " / Slot" + std::to_string(slot + 1); |
| | | m_listCtrl.InsertChild(root2, { pGlass->getID().c_str(), _T("Glass"), |
| | | pGlass->getStateText().c_str(), _T(""), carrier.c_str(), _T("") }); |
| | | } |
| | | else { |
| | | m_listCtrl.InsertChild(root2, { "Null", _T("Glass"), _T(""), _T(""), c.carrierId.c_str(), _T("") }); |
| | | } |
| | | } |
| | | } |
| | | root2->expanded = true; |
| | | } |
| | | root1->expanded = true; |
| | | |
| | | |
| | | m_listCtrl.RebuildVisible(); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "CExpandableListCtrl.h" |
| | | #include "CControlJob.h" |
| | | |
| | | |
| | | // CControlJobDlg å¯¹è¯æ¡ |
| | | |
| | | class CControlJobDlg : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CControlJobDlg) |
| | | |
| | | public: |
| | | CControlJobDlg(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CControlJobDlg(); |
| | | |
| | | public: |
| | | void SetControlJob(SERVO::CControlJob* pControlJob); |
| | | |
| | | private: |
| | | void Resize(); |
| | | void ShowGroup1(BOOL bShow); |
| | | void ShowGroup2(BOOL bShow); |
| | | void LoadData(); |
| | | |
| | | private: |
| | | SERVO::CControlJob* m_pControlJob; |
| | | CFont m_fontNoJob; |
| | | |
| | | protected: |
| | | CExpandableListCtrl m_listCtrl; |
| | | |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_CONTROL_JOB }; |
| | | #endif |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | public: |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnSize(UINT nType, int cx, int cy); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CExpandableListCtrl.h" |
| | | |
| | | IMPLEMENT_DYNAMIC(CExpandableListCtrl, CListCtrl) |
| | | |
| | | CExpandableListCtrl::CExpandableListCtrl() {} |
| | | CExpandableListCtrl::~CExpandableListCtrl() {} |
| | | |
| | | BEGIN_MESSAGE_MAP(CExpandableListCtrl, CListCtrl) |
| | | ON_WM_CREATE() |
| | | ON_NOTIFY_REFLECT(NM_CLICK, &CExpandableListCtrl::OnClick) |
| | | ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CExpandableListCtrl::OnCustomDraw) |
| | | END_MESSAGE_MAP() |
| | | |
| | | int CExpandableListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) |
| | | { |
| | | if (CListCtrl::OnCreate(lpCreateStruct) == -1) |
| | | return -1; |
| | | |
| | | // æ¥è¡¨é£æ ¼åä¸¾ä¾ |
| | | SetExtendedStyle(GetExtendedStyle() |
| | | | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void CExpandableListCtrl::PreSubclassWindow() |
| | | { |
| | | // æ¥è¡¨é£æ ¼åä¸¾ä¾ |
| | | SetExtendedStyle(GetExtendedStyle() |
| | | | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER); |
| | | |
| | | CListCtrl::PreSubclassWindow(); |
| | | } |
| | | |
| | | CExpandableListCtrl::Node* CExpandableListCtrl::InsertRoot(const std::vector<CString>& cols) |
| | | { |
| | | auto n = std::make_unique<Node>((int)max(1, (int)cols.size())); |
| | | for (size_t i = 0; i < cols.size(); ++i) n->cols[i] = cols[i]; |
| | | n->level = 0; |
| | | Node* raw = n.get(); |
| | | m_roots.emplace_back(std::move(n)); |
| | | return raw; |
| | | } |
| | | |
| | | CExpandableListCtrl::Node* CExpandableListCtrl::InsertChild(Node* parent, const std::vector<CString>& cols) |
| | | { |
| | | ASSERT(parent); |
| | | auto n = std::make_unique<Node>((int)max(1, (int)cols.size())); |
| | | for (size_t i = 0; i < cols.size(); ++i) n->cols[i] = cols[i]; |
| | | n->parent = parent; |
| | | n->level = parent->level + 1; |
| | | Node* raw = n.get(); |
| | | parent->children.emplace_back(std::move(n)); |
| | | return raw; |
| | | } |
| | | |
| | | void CExpandableListCtrl::appendVisible(Node* n) |
| | | { |
| | | m_visible.push_back(n); |
| | | if (n->expanded) { |
| | | for (auto& ch : n->children) { |
| | | appendVisible(ch.get()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CExpandableListCtrl::RebuildVisible() |
| | | { |
| | | // 1) é建å¯è§åºå |
| | | m_visible.clear(); |
| | | for (auto& r : m_roots) appendVisible(r.get()); |
| | | |
| | | // 2) éç»/éå¡«æ°æ® |
| | | SetRedraw(FALSE); |
| | | DeleteAllItems(); |
| | | |
| | | // æå
¥å¯è§è¡ |
| | | for (int i = 0; i < (int)m_visible.size(); ++i) { |
| | | Node* n = m_visible[i]; |
| | | LVITEM lvi{}; |
| | | lvi.mask = LVIF_TEXT; |
| | | lvi.iItem = i; |
| | | lvi.iSubItem = 0; |
| | | lvi.pszText = const_cast<LPTSTR>((LPCTSTR)(n->cols.empty() ? _T("") : n->cols[0])); |
| | | InsertItem(&lvi); |
| | | |
| | | for (int col = 1; col < GetHeaderCtrl()->GetItemCount(); ++col) { |
| | | CString txt = (col < (int)n->cols.size()) ? n->cols[col] : _T(""); |
| | | SetItemText(i, col, txt); |
| | | } |
| | | } |
| | | SetRedraw(TRUE); |
| | | Invalidate(); |
| | | } |
| | | |
| | | void CExpandableListCtrl::Expand(Node* n) |
| | | { |
| | | if (!n || n->children.empty()) return; |
| | | if (!n->expanded) { n->expanded = true; RebuildVisible(); } |
| | | } |
| | | |
| | | void CExpandableListCtrl::Collapse(Node* n) |
| | | { |
| | | if (!n || n->children.empty()) return; |
| | | if (n->expanded) { n->expanded = false; RebuildVisible(); } |
| | | } |
| | | |
| | | void CExpandableListCtrl::Toggle(Node* n) |
| | | { |
| | | if (!n || n->children.empty()) return; |
| | | n->expanded = !n->expanded; |
| | | RebuildVisible(); |
| | | } |
| | | |
| | | CExpandableListCtrl::Node* CExpandableListCtrl::GetNodeByVisibleIndex(int i) const |
| | | { |
| | | if (i < 0 || i >= (int)m_visible.size()) return nullptr; |
| | | return m_visible[i]; |
| | | } |
| | | |
| | | CRect CExpandableListCtrl::expanderRectForRow(int row) const |
| | | { |
| | | CRect rcLabel; |
| | | if (!const_cast<CExpandableListCtrl*>(this)->GetSubItemRect(row, 0, LVIR_LABEL, rcLabel)) |
| | | return CRect(0, 0, 0, 0); |
| | | |
| | | Node* n = const_cast<CExpandableListCtrl*>(this)->GetNodeByVisibleIndex(row); |
| | | if (!n || n->children.empty()) |
| | | return CRect(0, 0, 0, 0); // å¶åä¸å ä½ï¼ææ¬å°±ä¸ä¼è¢«å¤æ¨ä¸æ ¼ |
| | | |
| | | const int indent = n->level; |
| | | const int left = rcLabel.left + m_expanderPadding + indent * 16; |
| | | |
| | | return CRect( |
| | | left, |
| | | rcLabel.CenterPoint().y - m_expanderSize / 2, |
| | | left + m_expanderSize, |
| | | rcLabel.CenterPoint().y + m_expanderSize / 2 |
| | | ); |
| | | } |
| | | |
| | | |
| | | void CExpandableListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | LPNMITEMACTIVATE pia = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); |
| | | if (pia->iItem >= 0) { |
| | | CPoint pt = pia->ptAction; |
| | | |
| | | // å½ä¸å±å¼æé®ï¼ |
| | | CRect expRc = expanderRectForRow(pia->iItem); |
| | | if (expRc.PtInRect(pt)) { |
| | | Node* n = GetNodeByVisibleIndex(pia->iItem); |
| | | if (n && !n->children.empty()) { |
| | | Toggle(n); |
| | | } |
| | | } |
| | | } |
| | | *pResult = 0; |
| | | } |
| | | |
| | | void CExpandableListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | LPNMLVCUSTOMDRAW pCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR); |
| | | |
| | | switch (pCD->nmcd.dwDrawStage) |
| | | { |
| | | case CDDS_PREPAINT: |
| | | *pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYSUBITEMDRAW; |
| | | return; |
| | | |
| | | case CDDS_ITEMPREPAINT: |
| | | *pResult = CDRF_NOTIFYSUBITEMDRAW; |
| | | return; |
| | | |
| | | case CDDS_ITEMPREPAINT | CDDS_SUBITEM: |
| | | { |
| | | const int row = (int)pCD->nmcd.dwItemSpec; |
| | | const int col = pCD->iSubItem; |
| | | CDC* pDC = CDC::FromHandle(pCD->nmcd.hdc); |
| | | |
| | | if (col == 0) |
| | | { |
| | | CRect rc; GetSubItemRect(row, 0, LVIR_LABEL, rc); |
| | | Node* n = GetNodeByVisibleIndex(row); |
| | | if (!n) { *pResult = CDRF_DODEFAULT; return; } |
| | | |
| | | // 1) èæ¯/忝é¢è²ï¼ææ¯å¦éä¸ |
| | | const bool selected = (GetItemState(row, LVIS_SELECTED) & LVIS_SELECTED) != 0; |
| | | const bool focusOnCtrl = (GetSafeHwnd() == ::GetFocus()); |
| | | COLORREF bk = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHT : COLOR_3DFACE) |
| | | : ListView_GetBkColor(m_hWnd); |
| | | COLORREF txt = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) |
| | | : ListView_GetTextColor(m_hWnd); |
| | | |
| | | // ä»
å¨éè¦æ¶å¡«å
èæ¯ï¼é¿å
âé»ä¸çâï¼ |
| | | CBrush bkBrush(bk); |
| | | pDC->FillRect(rc, &bkBrush); |
| | | |
| | | // 2) å±å¼/æå æç¤ºï¼åèæ§é¡¹ç®çå³å¯¹é½åæ æ³ï¼ååç´ å¯¹é½ï¼çº¯GDIï¼ |
| | | if (!n->children.empty()) |
| | | { |
| | | CRect box = expanderRectForRow(row); |
| | | |
| | | // ---- å¯è°åæ°ï¼ä¸æ§ä»£ç å½åä¸è´ ---- |
| | | // å³ä¾§çç½ï¼ä¸ææ¬é´é/ç½æ ¼çº¿ä¿æè·ç¦»ï¼ |
| | | const int ROFFSET = 2; |
| | | // éå/å±å¼çâ宽度â设置ï¼å¥æ°æ´é¡ºç¼ï¼9/11 é½è¡ï¼ |
| | | const int WIDE = max(9, min(min(box.Width(), box.Height()), 13)); // â¶ çè¾¹é¿ |
| | | const int WIDE2 = WIDE / 2; // ä¸å |
| | | const int EXPANDED_WIDE = WIDE; // â¼ çè¾¹é¿ |
| | | |
| | | // 轻微å
缩ï¼é¿å
è´´è¾¹ï¼ä¸ä½ æ§ä»£ç âæé®è¦å·ä¸ä¸âåæï¼ |
| | | box.DeflateRect(1, 1); |
| | | |
| | | // ç»ä¸åå¶æ°å¯¹é½ï¼åå°ååç´ é¯é½¿ |
| | | auto even = [](int v) { return (v & 1) ? (v - 1) : v; }; |
| | | |
| | | // 计ç®âèªä¸åä¸âçåºååç§»ï¼ä¸æ§ TreeCtrl ä¸è´ |
| | | // è¿éç¨ box ä½ä¸º pRect |
| | | POINT pt[3]; |
| | | if (n->expanded) { |
| | | // â¼ |
| | | int nBottomOffset = (box.Height() - EXPANDED_WIDE) / 2; |
| | | pt[0].x = box.right - ROFFSET - EXPANDED_WIDE; |
| | | pt[0].y = box.bottom - nBottomOffset; |
| | | pt[1].x = box.right - ROFFSET; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - EXPANDED_WIDE; |
| | | } |
| | | else { |
| | | // â¶ |
| | | int nBottomOffset = (box.Height() - WIDE) / 2; |
| | | |
| | | pt[0].x = box.right - ROFFSET - WIDE2; |
| | | pt[0].y = box.bottom - nBottomOffset - WIDE; |
| | | pt[1].x = box.right - ROFFSET - WIDE2; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - WIDE2; |
| | | } |
| | | |
| | | // ä»
å¡«å
ï¼ä¸æè¾¹ï¼æè¾¹ä¼å éå°é¶æï¼ï¼é¢è²ç¨ txt ä¸ä¸»é¢ä¸è´ |
| | | HGDIOBJ oldPen = pDC->SelectObject(GetStockObject(NULL_PEN)); |
| | | HBRUSH hBrush = CreateSolidBrush(txt); |
| | | HGDIOBJ oldBrush = pDC->SelectObject(hBrush); |
| | | |
| | | pDC->Polygon(pt, 3); |
| | | |
| | | pDC->SelectObject(oldPen); |
| | | pDC->SelectObject(oldBrush); |
| | | DeleteObject(hBrush); |
| | | } |
| | | |
| | | |
| | | |
| | | // 3) ææ¬ï¼åºäºé¦ååºåå³ç§»ï¼åºåæ¯å¦æåèç¹ï¼ |
| | | const int indentPx = n->level * 14; |
| | | const int baseLeft = rc.left + m_expanderPadding + indentPx; |
| | | |
| | | CRect textRc = rc; |
| | | if (!n->children.empty()) { |
| | | // æå项ï¼é¢çæé®ä½ + ææ¬é´é |
| | | textRc.left = baseLeft + m_expanderSize + m_textGap; |
| | | } |
| | | else { |
| | | // å¶åè¡ï¼ä¸é¢çæé®ä½ï¼åªç»ä¸ç¹ç¹å¶åé´éï¼è®©å±çº§ç¼©è¿ä»ç¶çæï¼ |
| | | constexpr int kLeafGap = 2; // ä½ å¯è° 0~4 |
| | | textRc.left = baseLeft + kLeafGap; |
| | | } |
| | | |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(txt); |
| | | CString txt0 = n->cols.empty() ? _T("") : n->cols[0]; |
| | | pDC->DrawText(txt0, textRc, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_END_ELLIPSIS); |
| | | |
| | | |
| | | // ââ ç»å®ä¸è§ä¸ææ¬ä¹åï¼è¡¥ä¸æ¡è¯¥è¡çåºé¨æ¨ªåç½æ ¼çº¿ ââ |
| | | // ä»
å½å¼å¯äº LVS_EX_GRIDLINES æç»å¶ |
| | | if (GetExtendedStyle() & LVS_EX_GRIDLINES) |
| | | { |
| | | // ç¨æ´è¡ boundsï¼ä¿è¯æ¨ªçº¿è´¯ç©¿ææåçå¯è§å®½åº¦ |
| | | CRect rcRow; |
| | | GetSubItemRect(row, 0, LVIR_BOUNDS, rcRow); |
| | | |
| | | // åºè¾¹ y åæ ï¼ä¸ç³»ç»ç½æ ¼çº¿å¯¹é½ï¼ |
| | | const int y = rcRow.bottom - 1; |
| | | |
| | | // é¢è²ä¸ç³»ç»é£æ ¼æ¥è¿ï¼è¥è§å¾åæµ
ï¼å¯æ¢ COLOR_3DSHADOW |
| | | CPen pen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT)); |
| | | CPen* oldPen = pDC->SelectObject(&pen); |
| | | |
| | | // 横线ä»è¡å·¦å°è¡å³ï¼å½åå¯è§åºåï¼ |
| | | pDC->MoveTo(rcRow.left, y); |
| | | pDC->LineTo(rcRow.right, y); |
| | | |
| | | pDC->SelectObject(oldPen); |
| | | } |
| | | |
| | | *pResult = CDRF_SKIPDEFAULT; |
| | | return; |
| | | } |
| | | |
| | | // å
¶ä»åé»è®¤ç»å¶ |
| | | *pResult = CDRF_DODEFAULT; |
| | | return; |
| | | } |
| | | |
| | | } |
| | | |
| | | *pResult = CDRF_DODEFAULT; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <vector> |
| | | #include <memory> |
| | | |
| | | class CExpandableListCtrl : public CListCtrl |
| | | { |
| | | DECLARE_DYNAMIC(CExpandableListCtrl) |
| | | |
| | | public: |
| | | struct Node { |
| | | Node* parent = nullptr; |
| | | std::vector<std::unique_ptr<Node>> children; |
| | | std::vector<CString> cols; // ååææ¬ |
| | | bool expanded = false; |
| | | int level = 0; // 缩è¿å±çº§ |
| | | |
| | | Node(int nCols = 1) : cols(nCols) {} |
| | | }; |
| | | |
| | | CExpandableListCtrl(); |
| | | virtual ~CExpandableListCtrl(); |
| | | |
| | | // æ°æ®æå»º |
| | | Node* InsertRoot(const std::vector<CString>& cols); |
| | | Node* InsertChild(Node* parent, const std::vector<CString>& cols); |
| | | |
| | | // å±å¼/æå |
| | | void Expand(Node* n); |
| | | void Collapse(Node* n); |
| | | void Toggle(Node* n); |
| | | |
| | | // å·æ°å¯è§å表 |
| | | void RebuildVisible(); |
| | | |
| | | // 便æ·ï¼éè¿å¯è§è¡å·å Node* |
| | | Node* GetNodeByVisibleIndex(int i) const; |
| | | |
| | | private: |
| | | void appendVisible(Node* n); |
| | | CRect expanderRectForRow(int row) const; // é¦åå±å¼æé®åºå |
| | | virtual void PreSubclassWindow(); |
| | | |
| | | protected: |
| | | // æ¶æ¯ |
| | | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); |
| | | afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); |
| | | DECLARE_MESSAGE_MAP() |
| | | |
| | | private: |
| | | std::vector<std::unique_ptr<Node>> m_roots; // é¡¶å±èç¹ |
| | | std::vector<Node*> m_visible; // å±å¼åçå¯è§èç¹é¡ºåº |
| | | int m_expanderPadding = 6; // é¦åå
ä¾§è¾¹è· |
| | | int m_expanderSize = 10; // å°ä¸è§/æ¹åå¤§å° |
| | | int m_textGap = 6; |
| | | }; |
| | | |
| | | |
| | |
| | | m_nOriginPort = 0; |
| | | m_nOriginSlot = 0; |
| | | m_bScheduledForProcessing = FALSE; |
| | | m_pProcessJob = nullptr; |
| | | } |
| | | |
| | | CGlass::~CGlass() |
| | |
| | | void CGlass::setScheduledForProcessing(BOOL bProcessing) |
| | | { |
| | | m_bScheduledForProcessing = bProcessing; |
| | | } |
| | | |
| | | CProcessJob* CGlass::getProcessJob() |
| | | { |
| | | return m_pProcessJob; |
| | | } |
| | | |
| | | void CGlass::setProcessJob(CProcessJob* pProcessJob) |
| | | { |
| | | m_pProcessJob = pProcessJob; |
| | | } |
| | | |
| | | CPath* CGlass::getPath() |
| | |
| | | |
| | | return pPath->getInspResult(); |
| | | } |
| | | |
| | | std::string CGlass::getStateText() |
| | | { |
| | | switch (m_state) |
| | | { |
| | | case SERVO::GlsState::NoState: |
| | | return "NoState"; |
| | | break; |
| | | case SERVO::GlsState::Queued: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::GlsState::InProcess: |
| | | return "InProcess"; |
| | | break; |
| | | case SERVO::GlsState::Paused: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::GlsState::Completed: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::GlsState::Aborted: |
| | | return "Aborted"; |
| | | break; |
| | | case SERVO::GlsState::Failed: |
| | | return "Failed"; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | bool CGlass::queue() { |
| | | if (m_state != GlsState::NoState) return false; |
| | | markQueued(); |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::start() { |
| | | if (m_state != GlsState::Queued && m_state != GlsState::Paused) |
| | | return false; |
| | | if (!m_tStart.has_value()) markStart(); |
| | | m_state = GlsState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::pause() { |
| | | if (m_state != GlsState::InProcess) return false; |
| | | m_state = GlsState::Paused; |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::resume() { |
| | | if (m_state != GlsState::Paused) return false; |
| | | m_state = GlsState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::complete() { |
| | | if (m_state != GlsState::InProcess && m_state != GlsState::Paused) return false; |
| | | m_state = GlsState::Completed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::abort() { |
| | | if (m_state == GlsState::Completed || m_state == GlsState::Aborted || m_state == GlsState::Failed) |
| | | return false; |
| | | m_state = GlsState::Aborted; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CGlass::fail(std::string reason) |
| | | { |
| | | m_failReason = trimCopy(reason); |
| | | clampString(m_failReason, 128); |
| | | m_state = GlsState::Failed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | std::string CGlass::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; |
| | | } |
| | | |
| | | void CGlass::clampString(std::string& s, size_t maxLen) |
| | | { |
| | | if (s.size() > maxLen) s.resize(maxLen); |
| | | } |
| | | |
| | | // ââ æ¶é´æ³ & å·¥å
· ââ |
| | | void CGlass::markQueued() |
| | | { |
| | | m_state = GlsState::Queued; |
| | | m_tQueued = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CGlass::markStart() |
| | | { |
| | | m_tStart = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CGlass::markEnd() |
| | | { |
| | | m_tEnd = std::chrono::system_clock::now(); |
| | | } |
| | | } |
| | |
| | | #include "CJobDataC.h" |
| | | #include "CJobDataS.h" |
| | | #include "ServoCommo.h" |
| | | #include "ProcessJob.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | | /// PJ çå½å¨æï¼è´´è¿ E40 常è§ç¶æï¼ |
| | | enum class GlsState : uint8_t { |
| | | NoState = 0, |
| | | Queued, |
| | | InProcess, |
| | | Paused, |
| | | Completed, |
| | | Aborted, |
| | | Failed |
| | | }; |
| | | |
| | | class CGlass : public CContext |
| | | { |
| | | public: |
| | |
| | | void getOrginPort(int& port, int& slot); |
| | | BOOL isScheduledForProcessing(); |
| | | void setScheduledForProcessing(BOOL bProcessing); |
| | | CProcessJob* getProcessJob(); |
| | | void setProcessJob(CProcessJob* pProcessJob); |
| | | CPath* getPathWithEq(unsigned int nEqId, unsigned int nUnit); |
| | | CPath* getPath(); |
| | | void addPath(unsigned int nEqId, unsigned int nUnit); |
| | |
| | | int setInspResult(unsigned int nEqId, unsigned int nUnit, InspResult result); |
| | | InspResult getInspResult(unsigned int nEqId, unsigned int nUnit); |
| | | |
| | | public: |
| | | // æ°å¢ç¶æ |
| | | GlsState state() const noexcept { return m_state; } |
| | | std::string getStateText(); |
| | | GlsState m_state{ GlsState::NoState }; |
| | | static void clampString(std::string& s, size_t maxLen); |
| | | static std::string trimCopy(std::string s); |
| | | std::string m_failReason; |
| | | |
| | | // ââ ç¶ææºï¼å¸¦å®å«ï¼ââ |
| | | bool queue(); // NoState -> Queued |
| | | bool start(); // Queued -> InProcess |
| | | bool pause(); // InProcess -> Paused |
| | | bool resume(); // Paused -> InProcess |
| | | bool complete(); // InProcess -> Completed |
| | | bool abort(); // Any (æªç»æ) -> Aborted |
| | | bool fail(std::string reason); // ä»»ææ -> Failedï¼è®°å½å¤±è´¥åå ï¼ |
| | | |
| | | // æ¶é´æ³ |
| | | 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; |
| | | |
| | | // æ¶é´æ³ï¼å¯ç¨äºæ¥è¡¨/è¿½æº¯ï¼ |
| | | 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; } |
| | | void markQueued(); |
| | | void markStart(); |
| | | void markEnd(); |
| | | |
| | | private: |
| | | MaterialsType m_type; |
| | | std::string m_strID; |
| | |
| | | int m_nOriginPort; |
| | | int m_nOriginSlot; |
| | | BOOL m_bScheduledForProcessing; /* æ¯å¦å°å å·¥å¤ç */ |
| | | CProcessJob* m_pProcessJob; |
| | | }; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | // æ¨¡ææµè¯ |
| | | /* |
| | | if (m_nIndex == 0) { |
| | | static int ii = 0; |
| | | ii++; |
| | |
| | | CPortStatusReport portStatusReport; |
| | | portStatusReport.setPortStatus(PORT_INUSE); |
| | | portStatusReport.setJobExistenceSlot(0xf); |
| | | portStatusReport.setCassetteId("CID1984113"); |
| | | portStatusReport.setCassetteId("CID1001"); |
| | | int nRet = portStatusReport.serialize(szBuffer, 64); |
| | | decodePortStatusReport(pStep, szBuffer, 64); |
| | | } |
| | | } |
| | | */ |
| | | if (m_nIndex == 1) { |
| | | static int ii = 0; |
| | | ii++; |
| | | if (ii == 55) { |
| | | char szBuffer[64] = { 0 }; |
| | | CStep* pStep = getStepWithName(STEP_EQ_PORT2_INUSE); |
| | | CPortStatusReport portStatusReport; |
| | | portStatusReport.setPortStatus(PORT_INUSE); |
| | | portStatusReport.setJobExistenceSlot(0xff ); |
| | | portStatusReport.setCassetteId("CID1004"); |
| | | int nRet = portStatusReport.serialize(szBuffer, 64); |
| | | decodePortStatusReport(pStep, szBuffer, 64); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CLoadPort::serialize(CArchive& ar) |
| | |
| | | #include "CMaster.h" |
| | | #include <future> |
| | | #include <vector> |
| | | #include "RecipeManager.h" |
| | | #include <fstream> |
| | | #include "SerializeUtil.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | m_bEnableAlarmReport = true; |
| | | m_bContinuousTransfer = false; |
| | | m_nContinuousTransferCount = 0; |
| | | m_nContinuousTransferStep = CTStep_begin; |
| | | 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_hEventReadBitsThreadExit[0] = nullptr; |
| | |
| | | // Measurement -> LoadPort |
| | | for (int s = 0; s < 4; s++) { |
| | | PortType pt = pLoadPorts[s]->getPortType(); |
| | | if (!rmd.armState[0] && pLoadPorts[s]->isEnable() |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_BakeCooling_Measurement) |
| | | && !rmd.armState[0] && pLoadPorts[s]->isEnable() |
| | | && (pt == PortType::Unloading || pt == PortType::Both) |
| | | && pLoadPorts[s]->getPortStatus() == PORT_INUSE) { |
| | | for (int slot = 0; slot < SLOT_MAX; slot++) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pMeasurement, |
| | | 0, pLoadPorts[s], slot); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_Measurement_LoadPort; |
| | | m_nContinuousTransferStep = CTStep_end; |
| | | goto CT_PORT_PUT; |
| | | } |
| | |
| | | |
| | | |
| | | // BakeCooling ->Measurement |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_BakeCooling_BakeCooling3) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling, |
| | | 3, pMeasurement, 0); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_BakeCooling_Measurement; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(BakeCooling -> Measurement)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | |
| | | |
| | | |
| | | // BakeCoolingå
é¨ |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_BakeCooling_BakeCooling2) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling, |
| | | 2, pBakeCooling, 3); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_BakeCooling_BakeCooling3; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(BakeCooling-2 -> BakeCooling-3)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_BakeCooling_BakeCooling1) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling, |
| | | 1, pBakeCooling, 2); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_BakeCooling_BakeCooling2; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(BakeCooling-1 -> BakeCooling-2)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_VacuumBake_BakeCooling) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling, |
| | | 0, pBakeCooling, 1); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_BakeCooling_BakeCooling1; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(BakeCooling-0 -> BakeCooling-1)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // VacuumBake(G1) -> BakeCooling |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_VacuumBake_VacuumBake) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pVacuumBake, |
| | | 1, pBakeCooling, 0); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_VacuumBake_BakeCooling; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(VacuumBake(G1) -> BakeCooling)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // VacuumBake(G1) -> VacuumBake(G1) |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Bonder2_VacuumBake) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pVacuumBake, |
| | | 0, pVacuumBake, 1); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_VacuumBake_VacuumBake; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(VacuumBake(G1-0) -> VacuumBake(G1-1))..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // Bonder2 -> VacuumBake(G1) |
| | | if (!rmd.armState[0]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Bonder1_Bonder2) |
| | | && !rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder2, |
| | | 1, pVacuumBake, 0); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_Bonder2_VacuumBake; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(Bonder2 -> VacuumBake(G1))..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // Bonder1 -> Bonder2 |
| | | if (!rmd.armState[0] && !pBonder2->hasBondClass()) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Fliper_Bonder1) |
| | | && !rmd.armState[0] && !pBonder2->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder1, |
| | | 1, pBonder2, 1); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_Bonder1_Bonder2; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(Bonder1 -> Bonder2)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // Fliper(G2) -> Bonder1 |
| | | if (!rmd.armState[0] && !pBonder1->hasBondClass()) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Aligner_Fliper) |
| | | &&!rmd.armState[0] && !pBonder1->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pFliper, |
| | | 0, pBonder1, 1, 2); |
| | | 0, pBonder1, 1); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_Fliper_Bonder1; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(Fliper(G2) -> Bonder1)..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | } |
| | | |
| | | // Aligner -> Fliper(G2) |
| | | if (!rmd.armState[1]) { |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_LoadPort_Aligner) |
| | | && !rmd.armState[1]) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pAligner, |
| | | 0, pFliper, 0); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_Aligner_Fliper; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(Aligner -> Fliper(G2))..."); |
| | | } |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | |
| | | // LoadPort -> Aligner |
| | | for (int s = 0; s < 4; s++) { |
| | | PortType pt = pLoadPorts[s]->getPortType(); |
| | | if (!rmd.armState[0] && pLoadPorts[s]->isEnable() |
| | | if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_end) |
| | | && !rmd.armState[0] && pLoadPorts[s]->isEnable() |
| | | && (pt == PortType::Loading || pt == PortType::Both) |
| | | && pLoadPorts[s]->getPortStatus() == PORT_INUSE) { |
| | | for (int slot = 0; slot < SLOT_MAX; slot++) { |
| | | m_pActiveRobotTask = createTransferTask_continuous_transfer(pLoadPorts[s], |
| | | slot, pAligner, 0); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_nContinuousTransferStep = CTStep_LoadPort_Aligner; |
| | | LOGI("<ContinuousTransfer>åä¼ æµè¯ï¼å¼å§æ¬éä»»å¡(LoadPort -> Aligner)..."); |
| | | pEFEM->setContext(m_pActiveRobotTask->getContext()); |
| | | goto CT_PORT_GET; |
| | |
| | | }; |
| | | listener.onPortStatusChanged = [&](void* pEquipment, short status, __int64 data) { |
| | | LOGE("<Master-%s>onPortStatusChangedãstatus=%d, data=%lld", ((CEquipment*)pEquipment)->getName().c_str(), status); |
| | | if (status == PORT_INUSE && m_pControlJob != nullptr) { |
| | | CLoadPort* pPort = (CLoadPort*)pEquipment; |
| | | auto pjs = m_pControlJob->getPjs(); |
| | | for (auto pj : pjs) { |
| | | auto carrier = pj->getCarrier(pPort->getCassetteId()); |
| | | if (carrier != nullptr) { |
| | | for (auto slot : carrier->slots) { |
| | | CGlass* pGlass = pPort->getGlassFromSlot(slot); |
| | | carrier->contexts.push_back((void*)pGlass); |
| | | if (pGlass != nullptr) { |
| | | pGlass->setProcessJob(pj); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | if (m_listener.onLoadPortStatusChanged != nullptr) { |
| | | m_listener.onLoadPortStatusChanged(this, (CEquipment*)pEquipment, status, data); |
| | | } |
| | |
| | | } |
| | | |
| | | CEquipment* CMaster::getEquipment(int id) |
| | | { |
| | | for (auto item : m_listEquipment) { |
| | | if (item->getID() == id) return item; |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CEquipment* CMaster::getEquipment(int id) const |
| | | { |
| | | for (auto item : m_listEquipment) { |
| | | if (item->getID() == id) return item; |
| | |
| | | { |
| | | m_nContinuousTransferCount = round; |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | m_processJobs = temp; |
| | | this->saveState(); |
| | | |
| | | return (int)m_processJobs.size(); |
| | | } |
| | | |
| | | 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); |
| | | this->saveState(); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | CControlJob* CMaster::getControlJob() |
| | | { |
| | | return m_pControlJob; |
| | | } |
| | | |
| | | CLoadPort* CMaster::getPortWithCarrierId(const std::string& carrierId) const |
| | | { |
| | | CLoadPort* pPort; |
| | | int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4}; |
| | | for (int i = 0; i < 4; i++) { |
| | | pPort = (CLoadPort*)getEquipment(eqid[i]); |
| | | ASSERT(pPort); |
| | | if (pPort->getCassetteId().compare(carrierId) == 0) return pPort; |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | bool CMaster::isProcessJobsEmpty() const |
| | | { |
| | | return m_processJobs.empty(); |
| | | } |
| | | |
| | | bool CMaster::recipeExists(const std::string& ppid) const |
| | | { |
| | | std::vector<std::string> vecRecipe = RecipeManager::getInstance().getAllPPID(); |
| | | bool exists = std::find(vecRecipe.begin(), vecRecipe.end(), ppid) != vecRecipe.end(); |
| | | return exists; |
| | | } |
| | | |
| | | bool CMaster::carrierPresent(const std::string& carrierId) const |
| | | { |
| | | CLoadPort* pPort = getPortWithCarrierId(carrierId); |
| | | return pPort != nullptr; |
| | | } |
| | | |
| | | bool CMaster::slotUsable(const std::string& carrierId, uint16_t slot) const |
| | | { |
| | | CLoadPort* pPort = getPortWithCarrierId(carrierId); |
| | | if(pPort == nullptr) return false; |
| | | CSlot* pSlot = pPort->getSlot(slot); |
| | | if (pSlot == nullptr) return false; |
| | | return pSlot->isEnable(); |
| | | } |
| | | |
| | | bool CMaster::ceidDefined(uint32_t ceid) const |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | bool CMaster::saveState() const |
| | | { |
| | | std::ofstream ofs(m_strStatePath, std::ios::binary); |
| | | if (!ofs) return false; |
| | | |
| | | // æä»¶å¤´ |
| | | uint32_t magic = 0x4D415354; // 'MAST' |
| | | uint16_t version = 1; |
| | | ofs.write(reinterpret_cast<const char*>(&magic), sizeof(magic)); |
| | | ofs.write(reinterpret_cast<const char*>(&version), sizeof(version)); |
| | | |
| | | // ä¿å ControlJob |
| | | bool hasCJ = (m_pControlJob != nullptr); |
| | | ofs.write(reinterpret_cast<const char*>(&hasCJ), sizeof(hasCJ)); |
| | | if (hasCJ) { |
| | | m_pControlJob->serialize(ofs); |
| | | } |
| | | |
| | | // ä¿å ProcessJob å表 |
| | | uint32_t count = static_cast<uint32_t>(m_processJobs.size()); |
| | | ofs.write(reinterpret_cast<const char*>(&count), sizeof(count)); |
| | | for (const auto& job : m_processJobs) { |
| | | job->serialize(ofs); |
| | | } |
| | | |
| | | // 以åå¯ä»¥å¨è¿éè¿½å æ°å段 |
| | | return true; |
| | | } |
| | | |
| | | bool CMaster::loadState(const std::string& path) |
| | | { |
| | | // ä¿åæä»¶è·¯å¾ |
| | | m_strStatePath = path; |
| | | |
| | | |
| | | std::ifstream ifs(path, std::ios::binary); |
| | | if (!ifs) return false; |
| | | |
| | | // æä»¶å¤´ |
| | | uint32_t magic = 0; |
| | | uint16_t version = 0; |
| | | ifs.read(reinterpret_cast<char*>(&magic), sizeof(magic)); |
| | | ifs.read(reinterpret_cast<char*>(&version), sizeof(version)); |
| | | |
| | | if (magic != 0x4D415354) { |
| | | // æä»¶ä¸åæ³ |
| | | return false; |
| | | } |
| | | |
| | | if (m_pControlJob != nullptr) { |
| | | delete m_pControlJob; |
| | | m_pControlJob = nullptr; |
| | | } |
| | | |
| | | // 读å ControlJob |
| | | bool hasCJ = false; |
| | | ifs.read(reinterpret_cast<char*>(&hasCJ), sizeof(hasCJ)); |
| | | if (hasCJ) { |
| | | m_pControlJob = new CControlJob(); |
| | | if (!CControlJob::deserialize(ifs, *m_pControlJob)) return false; |
| | | } |
| | | |
| | | |
| | | // 读å ProcessJob å表 |
| | | uint32_t count = 0; |
| | | ifs.read(reinterpret_cast<char*>(&count), sizeof(count)); |
| | | m_processJobs.clear(); |
| | | for (uint32_t i = 0; i < count; i++) { |
| | | CProcessJob* pProcessJob = new CProcessJob(); |
| | | if (!CProcessJob::deserialize(ifs, *pProcessJob)) return false; |
| | | m_processJobs.push_back(pProcessJob); |
| | | } |
| | | |
| | | |
| | | // æ¾å°CProcessJobæéå å
¥åè¡¨ä¸ |
| | | std::vector<CProcessJob*> tempPjs; |
| | | auto ids = m_pControlJob->pjIds(); |
| | | for (auto id : ids) { |
| | | auto pj = getProcessJob(id); |
| | | if (pj != nullptr) { |
| | | tempPjs.push_back(pj); |
| | | } |
| | | } |
| | | m_pControlJob->setPJs(tempPjs); |
| | | |
| | | |
| | | // å¦æçæ¬å级ï¼å¯å¨è¿é夿 version æ¥å è½½æ°å段 |
| | | |
| | | |
| | | return true; |
| | | } |
| | | } |
| | |
| | | #include "CArmTray.h" |
| | | #include "CCLinkIEControl.h" |
| | | #include "CRobotTask.h" |
| | | #include "ProcessJob.h" |
| | | #include "CControlJob.h" |
| | | |
| | | |
| | | #define CTStep_begin 0 |
| | | #define CTStep_end 99 |
| | | #define CTStep_Unknow 0 |
| | | #define CTStep_LoadPort_Aligner 1 |
| | | #define CTStep_Aligner_Fliper 2 |
| | | #define CTStep_Fliper_Bonder1 3 |
| | | #define CTStep_Bonder1_Bonder2 4 |
| | | #define CTStep_Bonder2_VacuumBake 5 |
| | | #define CTStep_VacuumBake_VacuumBake 6 |
| | | #define CTStep_VacuumBake_BakeCooling 7 |
| | | #define CTStep_BakeCooling_BakeCooling1 8 |
| | | #define CTStep_BakeCooling_BakeCooling2 9 |
| | | #define CTStep_BakeCooling_BakeCooling3 10 |
| | | #define CTStep_BakeCooling_Measurement 11 |
| | | #define CTStep_Measurement_LoadPort 12 |
| | | #define CTStep_begin CTStep_LoadPort_Aligner |
| | | #define CTStep_end CTStep_Measurement_LoadPort |
| | | |
| | | namespace SERVO { |
| | | enum class MASTERSTATE { |
| | |
| | | ONCTROUNDEND onCTRoundEnd; |
| | | } MasterListener; |
| | | |
| | | class CMaster |
| | | class CMaster : public IResourceView |
| | | { |
| | | public: |
| | | CMaster(); |
| | |
| | | void onTimer(UINT nTimerid); |
| | | std::list<CEquipment*>& getEquipmentList(); |
| | | CEquipment* getEquipment(int id); |
| | | CEquipment* getEquipment(int id) const; |
| | | void setCacheFilepath(const char* pszFilepath); |
| | | int abortCurrentTask(); |
| | | int restoreCurrentTask(); |
| | |
| | | int carrierRelease(unsigned int port); |
| | | int getContinuousTransferCount(); |
| | | void setContinuousTransferCount(int round); |
| | | int setProcessJobs(std::vector<CProcessJob*>& pjs); |
| | | std::vector<CProcessJob*>& getProcessJobs(); |
| | | CProcessJob* getProcessJob(const std::string& id); |
| | | int setControlJob(CControlJob& controlJob); |
| | | CControlJob* getControlJob(); |
| | | CLoadPort* getPortWithCarrierId(const std::string& carrierId) const; |
| | | bool saveState() const; |
| | | bool loadState(const std::string& path); |
| | | |
| | | private: |
| | | inline void lock() { EnterCriticalSection(&m_criticalSection); } |
| | |
| | | CRobotTask* createTransferTask_restore(CEquipment* pEqSrc, CLoadPort** pPorts); |
| | | CRobotTask* createTransferTask_continuous_transfer(CEquipment* pSrcEq, int nSrcSlot, |
| | | CEquipment* pTarEq, int nTarSlot, int armNo = 1); |
| | | |
| | | public: |
| | | // ââ IResourceView è¦å ââï¼æ³¨æ constï¼ |
| | | bool isProcessJobsEmpty() const override; |
| | | bool recipeExists(const std::string& ppid) const override; |
| | | bool carrierPresent(const std::string& carrierId) const override; |
| | | bool slotUsable(const std::string& carrierId, uint16_t slot) const override; |
| | | bool ceidDefined(uint32_t ceid) const override; |
| | | |
| | | private: |
| | | CRITICAL_SECTION m_criticalSection; |
| | |
| | | private: |
| | | bool m_bEnableEventReport; |
| | | bool m_bEnableAlarmReport; |
| | | SERVO::CControlJob* m_pControlJob; |
| | | std::vector<SERVO::CProcessJob*> m_processJobs; |
| | | std::string m_strStatePath; |
| | | }; |
| | | } |
| | | |
| | |
| | | if (_strcmpi("A20", pszFormat) == 0) { |
| | | return SVFromat::A20; |
| | | } |
| | | if (_strcmpi("L", pszFormat) == 0) { |
| | | return SVFromat::L; |
| | | } |
| | | |
| | | return SVFromat::U1; |
| | | } |
| | |
| | | } |
| | | if (SVFromat::A20 == format) { |
| | | return "A20"; |
| | | } |
| | | if (SVFromat::L == format) { |
| | | return "L"; |
| | | } |
| | | |
| | | return "U1"; |
| | |
| | | m_strValue = strTemp; |
| | | } |
| | | |
| | | void CVariable::setValue(std::vector<CVariable>& vars) |
| | | { |
| | | m_varsValue = vars; |
| | | } |
| | | |
| | | std::string CVariable::getValue() |
| | | { |
| | | std::string strRet; |
| | |
| | | |
| | | return strRet; |
| | | } |
| | | |
| | | __int64 CVariable::getIntValue() |
| | | { |
| | | if (m_format == SVFromat::U1 || m_format == SVFromat::U2 || m_format == SVFromat::I2) { |
| | | return m_nValue; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | std::vector<CVariable>& CVariable::getVarsValue() |
| | | { |
| | | return m_varsValue; |
| | | } |
| | | } |
| | |
| | | U2, |
| | | I2, |
| | | A20, |
| | | A50 |
| | | A50, |
| | | L |
| | | }; |
| | | |
| | | class CVariable |
| | |
| | | std::string& getRemark(); |
| | | void setValue(__int64 value); |
| | | void setValue(const char* pszValue); |
| | | void setValue(std::vector<CVariable>& vars); |
| | | std::string getValue(); |
| | | __int64 getIntValue(); |
| | | std::vector<CVariable>& getVarsValue(); |
| | | |
| | | private: |
| | | unsigned int m_nVarialbeId; |
| | |
| | | std::string m_strRemark; |
| | | __int64 m_nValue; |
| | | std::string m_strValue; |
| | | std::vector<CVariable> m_varsValue; |
| | | }; |
| | | } |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | void CHsmsPassive::addVariableValueToItem(ISECS2Item* pParent, SERVO::CVariable* pVariable) |
| | | { |
| | | ASSERT(pParent); |
| | | ASSERT(pVariable); |
| | | |
| | | |
| | | ISECS2Item* pItemList; |
| | | SERVO::SVFromat format = pVariable->getFormat(); |
| | | switch (format) |
| | | { |
| | | case SERVO::SVFromat::U1: |
| | | pParent->addU1Item((unsigned char)pVariable->getIntValue(), "SV"); |
| | | break; |
| | | case SERVO::SVFromat::U2: |
| | | pParent->addU2Item((unsigned char)pVariable->getIntValue(), "SV"); |
| | | break; |
| | | case SERVO::SVFromat::I2: |
| | | pParent->addI2Item((unsigned char)pVariable->getIntValue(), "SV"); |
| | | break; |
| | | case SERVO::SVFromat::A20: |
| | | case SERVO::SVFromat::A50: |
| | | pParent->addItem(pVariable->getValue().c_str(), "SV"); |
| | | break; |
| | | case SERVO::SVFromat::L: |
| | | pItemList = pParent->addItem(); |
| | | { |
| | | auto vars = pVariable->getVarsValue(); |
| | | for (auto v : vars) { |
| | | addVariableValueToItem(pItemList, &v); |
| | | } |
| | | } |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | void CHsmsPassive::linkEventReport(unsigned int CEID, unsigned int RPTID) |
| | | { |
| | | SERVO::CCollectionEvent* pEvent = getEvent(CEID); |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | // S1F1 |
| | | replyAreYouThere(pMessage); |
| | | } |
| | | else if (nStream == 1 && pHeader->function == 3) { |
| | | replySelectedEquipmentStatusData(pMessage); |
| | | } |
| | | else if (nStream == 1 && pHeader->function == 13) { |
| | | replyEstablishCommunications(pMessage); |
| | | } |
| | |
| | | } |
| | | 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); |
| | | } |
| | | }; |
| | | |
| | |
| | | m_pPassive->sendMessage(pMessage); |
| | | LOGI("<HSMS>[SECS Msg SEND]%s", pMessage->toString()); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | // S1F3 |
| | | int CHsmsPassive::replySelectedEquipmentStatusData(IMessage* pRecv) |
| | | { |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | | return ER_NOTSELECT; |
| | | } |
| | | |
| | | IMessage* pMessage = NULL; |
| | | HSMS_Create1Message(pMessage, m_nSessionId, 1, 4, pRecv->getHeader()->systemBytes); |
| | | ASSERT(pMessage); |
| | | |
| | | unsigned char SVU1 = 0; |
| | | unsigned int SVID = 0; |
| | | ISECS2Item* pBody = pRecv->getBody(); |
| | | if (pBody == nullptr || pBody->getType() != SITYPE::L) { |
| | | pMessage->getBody()->addU1Item(SVU1, "SV"); |
| | | goto MYREPLY; |
| | | } |
| | | if (!pBody->getSubItemU4(0, SVID)) { |
| | | pMessage->getBody()->addU1Item(SVU1, "SV"); |
| | | goto MYREPLY; |
| | | } |
| | | |
| | | SERVO::CVariable* pVariable = getVariable(SVID); |
| | | if (pVariable == nullptr) { |
| | | pMessage->getBody()->addU1Item(SVU1, "SV"); |
| | | goto MYREPLY; |
| | | } |
| | | addVariableValueToItem(pMessage->getBody(), pVariable); |
| | | |
| | | MYREPLY: |
| | | m_pPassive->sendMessage(pMessage); |
| | | LOGI("<HSMS>[SECS Msg SEND]%s", pMessage->toString()); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | |
| | | |
| | | return 0; |
| | | } |
| | |
| | | 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) |
| | | { |
| | | 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; |
| | | |
| | | |
| | | // è§£éæ°æ®ï¼å¾å°CProcessJob |
| | | ISECS2Item* pItemPjs, * pItemPj,* pItemCarriers, * pItemCarrier, *pItemSlots, *pItemRecipes; |
| | | unsigned int DATAID; |
| | | const char* pszPrjobid, *pszMF, *pszCarrierId, *pszRecipeName; |
| | | std::string strCarrierId; |
| | | unsigned int len; |
| | | unsigned char slot, PRRECIPEMETHOD; |
| | | std::vector<unsigned char> slots; |
| | | std::vector<SERVO::CProcessJob*> pjs; |
| | | |
| | | if (!pBody->getSubItemU4(0, DATAID)) return ER_PARAM_ERROR; |
| | | pItemPjs = pBody->getSubItem(1); |
| | | if (pItemPjs == nullptr) return ER_PARAM_ERROR; |
| | | for (int i = 0; i < pItemPjs->getSubItemSize(); i++) { |
| | | pItemPj = pItemPjs->getSubItem(i); |
| | | if (pItemPj == nullptr) continue; |
| | | if (!pItemPj->getSubItemString(0, pszPrjobid)) continue; |
| | | if (!pItemPj->getSubItemBinary(1, pszMF, len)) continue; |
| | | pItemCarriers = pItemPj->getSubItem(2); |
| | | if (pItemCarriers == nullptr) continue; |
| | | pItemRecipes = pItemPj->getSubItem(3); |
| | | if (pItemRecipes == nullptr) continue; |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob(pszPrjobid); |
| | | int size = pItemCarriers->getSubItemSize(); |
| | | for (int j = 0; j < size; j++) { |
| | | pItemCarrier = pItemCarriers->getSubItem(j); |
| | | strCarrierId.clear(); |
| | | if (pItemCarrier->getSubItemString(0, pszCarrierId)) { |
| | | strCarrierId = pszCarrierId; |
| | | } |
| | | |
| | | slots.clear(); |
| | | pItemSlots = pItemCarrier->getSubItem(1); |
| | | if (pItemSlots != nullptr) { |
| | | int size2 = pItemSlots->getSubItemSize(); |
| | | for (int k = 0; k < size2; k++) { |
| | | if (pItemSlots->getSubItemU1(k, slot)) { |
| | | slots.push_back(slot); |
| | | } |
| | | } |
| | | } |
| | | pj->addCarrier(strCarrierId, slots); |
| | | } |
| | | if (pItemRecipes->getSubItemU1(0, PRRECIPEMETHOD) |
| | | && pItemRecipes->getSubItemString(1, pszRecipeName)) { |
| | | pj->setRecipe(SERVO::RecipeMethod(PRRECIPEMETHOD), std::string(pszRecipeName)); |
| | | } |
| | | |
| | | pjs.push_back(pj); |
| | | } |
| | | |
| | | ASSERT(m_listener.onPRJobMultiCreate != nullptr); |
| | | int nRet = m_listener.onPRJobMultiCreate(this, pjs); |
| | | |
| | | |
| | | // å夿¥æ |
| | | IMessage* pMessage = NULL; |
| | | HSMS_Create1Message(pMessage, m_nSessionId, 16, 16, ++m_nSystemByte); |
| | | ASSERT(pMessage); |
| | | ISECS2Item* pItemPrjobIds = pMessage->getBody()->addItem(); |
| | | ISECS2Item* pItemErrors = pMessage->getBody()->addItem(); |
| | | bool bHasError = false; |
| | | for (auto p : pjs) { |
| | | if (p->issues().empty()) { |
| | | pItemPrjobIds->addItem(p->id().c_str(), "PRJOBID"); |
| | | } |
| | | else { |
| | | bHasError = true; |
| | | } |
| | | } |
| | | if (bHasError) { |
| | | pItemErrors->addBoolItem(false, "ACKA"); |
| | | ISECS2Item* pItemErrors2 = pItemErrors->addItem(); |
| | | for (auto p : pjs) { |
| | | if (!p->issues().empty()) { |
| | | ISECS2Item* pItemErr = pItemErrors2->addItem(); |
| | | pItemErr->addU4Item(p->issues()[0].code, "ERRCODE"); |
| | | pItemErr->addItem(("<" + p->id() + ">" + p->issues()[0].text).c_str(), "ERRTEXT"); |
| | | } |
| | | } |
| | | } |
| | | m_pPassive->sendMessage(pMessage); |
| | | LOGI("<HSMS>[SECS Msg SEND]S16F16 (SysByte=%u)", pMessage->getHeader()->systemBytes); |
| | | HSMS_Destroy1Message(pMessage); |
| | | |
| | | |
| | | // éæ¾æé®é¢(æªæ·»å å°master)çå
å |
| | | for (auto p : pjs) { |
| | | if(!p->issues().empty()) delete p; |
| | | } |
| | | pjs.clear(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | // S5F1 |
| | | int CHsmsPassive::requestAlarmReport(int ALCD, int ALID, const char* ALTX) |
| | | { |
| | |
| | | pItemList2->addU4Item(pReport->getReportId(), "RPTID"); |
| | | ISECS2Item* pItemList3 = pItemList2->addItem(); |
| | | |
| | | auto values = pReport->getVariables(); |
| | | for (auto item : values) { |
| | | pItemList3->addItem(item->getValue().c_str(), "V"); |
| | | auto vars = pReport->getVariables(); |
| | | for (auto var : vars) { |
| | | addVariableValueToItem(pItemList3, var); |
| | | } |
| | | pAction->setSendMessage(pMessage); |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | |
| | | return requestEventReportSend("CarrierID_Readed"); |
| | | } |
| | | |
| | | int CHsmsPassive::requestEventReportSend_PJ_Queued() |
| | | { |
| | | return requestEventReportSend("PJ_Queued"); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | |
| | | #include <map> |
| | | #include <set> |
| | | #include "CCollectionEvent.h" |
| | | #include "ProcessJob.h" |
| | | #include "CControlJob.h" |
| | | |
| | | |
| | | #define EQCONSTANT_VALUE_MAX 64 |
| | |
| | | const char* pszCarrierId, |
| | | 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; |
| | |
| | | EDALARMREPORT onEnableDisableAlarmReport; |
| | | QUERYPPIDLIST onQueryPPIDList; |
| | | CARRIERACTION onCarrierAction; |
| | | PRJOBMULTICREATE onPRJobMultiCreate; |
| | | CONTROLJOBCREATE onControlJobCreate; |
| | | } SECSListener; |
| | | |
| | | |
| | |
| | | |
| | | /* è®¾ç½®è½¯ä»¶çæ¬å· æå¤§é¿åº¦ 20 bytes */ |
| | | void setSoftRev(const char* pszRev); |
| | | |
| | | /* æ·»å åéå¼å°ISECS2Item */ |
| | | void addVariableValueToItem(ISECS2Item* pParent, SERVO::CVariable* pVariable); |
| | | |
| | | // è¿æ¥Report |
| | | void linkEventReport(unsigned int CEID, unsigned int RPTID); |
| | |
| | | // 设置åéå¼ |
| | | void setVariableValue(const char* pszName, __int64 value); |
| | | void setVariableValue(const char* pszName, const char* value); |
| | | void setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars); |
| | | |
| | | // 仿件ä¸å è½½CReportå表 |
| | | int loadReports(const char* pszFilepath); |
| | |
| | | int requestEventReportSend(unsigned int CEID); |
| | | int requestEventReportSend(const char* pszEventName); |
| | | int requestEventReportSend_CarrierID_Readed(); |
| | | int requestEventReportSend_PJ_Queued(); |
| | | |
| | | private: |
| | | void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName); |
| | |
| | | /* replyå¼å¤´ç彿°ä¸ºåå¤å½æ° */ |
| | | int replyAreYouThere(IMessage* pRecv); |
| | | int replyEstablishCommunications(IMessage* pRecv); |
| | | int replySelectedEquipmentStatusData(IMessage* pRecv); |
| | | int replyOnLine(IMessage* pRecv); |
| | | int replyOffLine(IMessage* pRecv); |
| | | int replyEquipmentConstantRequest(IMessage* pRecv); |
| | |
| | | int replyPurgeSpooledData(IMessage* pRecv); |
| | | int replyQueryPPIDList(IMessage* pRecv); |
| | | int replyTerminalDisplay(IMessage* pRecv); |
| | | int replyCreateObj(IMessage* pRecv); |
| | | int replyPRJobMultiCreate(IMessage* pRecv); |
| | | |
| | | private: |
| | | inline void Lock() { EnterCriticalSection(&m_criticalSection); } |
| | |
| | | ::CreateDirectory(strLogDir, NULL); |
| | | CLog::GetLog()->SetOnLogCallback([&](int level, const char* pszMessage) -> void { |
| | | notifyTextAndInt(RX_CODE_LOG, pszMessage, level); |
| | | }); |
| | | }); |
| | | CLog::GetLog()->SetAutoAppendTimeString(TRUE); |
| | | CLog::GetLog()->SetOutputTarget(OT_FILE); |
| | | CLog::GetLog()->SetLogsDir(strLogDir); |
| | |
| | | listener.onEQConstantRequest = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void { |
| | | // 卿¤å¡«å
常éå¼ï¼ç®åä»
æ¯å 1åè¿å |
| | | for (auto& item : eqcs) { |
| | | sprintf_s(item.szValue, 256, "Test%d", item.id+1); |
| | | sprintf_s(item.szValue, 256, "Test%d", item.id + 1); |
| | | } |
| | | }; |
| | | listener.onEQConstantSend = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void { |
| | |
| | | } |
| | | return ppids; |
| | | }; |
| | | listener.onCarrierAction = [&](void* pFrom, |
| | | unsigned int DATAID, |
| | | listener.onCarrierAction = [&](void* pFrom, |
| | | unsigned int DATAID, |
| | | const char* pszCarrierAction, |
| | | const char* pszCarrierId, |
| | | unsigned char PTN, |
| | |
| | | strErrorTxt = "rejected - invalid state"; |
| | | return CAACK_5; |
| | | LOGI("<Model>onCarrierAction %d, %s, %d, %d", DATAID, pszCarrierAction, pszCarrierId, PTN); |
| | | }; |
| | | listener.onPRJobMultiCreate = [&](void* pFrom, std::vector<SERVO::CProcessJob*>& pjs) -> int { |
| | | for (auto p : pjs) { |
| | | LOGI("<Model>onPRJobMultiCreate %s %s", p->id().c_str(), p->recipeSpec().c_str()); |
| | | } |
| | | int nRet = m_master.setProcessJobs(pjs); |
| | | auto processJobs = m_master.getProcessJobs(); |
| | | std::vector<SERVO::CVariable> vars; |
| | | for (auto pj : processJobs) { |
| | | SERVO::CVariable var("", "PRJOBID", "A50", "PRJOBID"); |
| | | var.setValue(pj->id().c_str()); |
| | | vars.push_back(var); |
| | | } |
| | | |
| | | 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_hsmsPassive.setEquipmentModelType((LPTSTR)(LPCTSTR)strModeType); |
| | |
| | | m_master.setCacheFilepath((LPTSTR)(LPCTSTR)strMasterDataFile); |
| | | m_master.setCompareMapsBeforeProceeding(m_configuration.isCompareMapsBeforeProceeding()); |
| | | |
| | | // å æªJob |
| | | strMasterDataFile.Format(_T("%s\\MasterState.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | std::string strPath = std::string((LPTSTR)(LPCTSTR)strMasterDataFile); |
| | | if (!m_master.loadState(strPath)) { |
| | | LOGE("<Master>å è½½MasterState.datæä»¶å¤±è´¥."); |
| | | } |
| | | |
| | | |
| | | // å è½½è¦åä¿¡æ¯ |
| | | AlarmManager& alarmManager = AlarmManager::getInstance(); |
| | | char szBuffer[MAX_PATH]; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "ProcessJob.h" |
| | | #include <cctype> |
| | | #include <fstream> |
| | | #include "SerializeUtil.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | | 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; |
| | | } |
| | | |
| | | CProcessJob::CProcessJob() |
| | | { |
| | | |
| | | } |
| | | |
| | | CProcessJob::CProcessJob(std::string pjId) |
| | | : m_pjId(trimCopy(pjId)) |
| | | { |
| | | clampString(m_pjId, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::setParentCjId(std::string cjId) { |
| | | m_parentCjId = trimCopy(cjId); |
| | | clampString(m_parentCjId, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::setRecipe(RecipeMethod method, std::string spec) { |
| | | m_recipeMethod = method; |
| | | m_recipeSpec = trimCopy(spec); |
| | | clampString(m_recipeSpec, MAX_ID_LEN); |
| | | } |
| | | |
| | | void CProcessJob::addParam(std::string name, std::string value) { |
| | | name = trimCopy(name); |
| | | value = trimCopy(value); |
| | | clampString(name, MAX_PARAM_K); |
| | | clampString(value, MAX_PARAM_V); |
| | | m_params.push_back({ std::move(name), std::move(value) }); |
| | | } |
| | | |
| | | void CProcessJob::setParams(std::vector<PJParam> params) { |
| | | m_params.clear(); |
| | | m_params.reserve(params.size()); |
| | | for (auto& p : params) addParam(std::move(p.name), std::move(p.value)); |
| | | } |
| | | |
| | | void CProcessJob::addPauseEvent(uint32_t ceid) { |
| | | if (ceid) m_pauseEvents.push_back(ceid); |
| | | std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); |
| | | m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); |
| | | } |
| | | |
| | | void CProcessJob::setPauseEvents(std::vector<uint32_t> ceids) { |
| | | m_pauseEvents = std::move(ceids); |
| | | std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); |
| | | m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); |
| | | } |
| | | |
| | | const std::vector<CProcessJob::ValidationIssue>& CProcessJob::issues() |
| | | { |
| | | return m_issues; |
| | | } |
| | | |
| | | bool CProcessJob::validate(const IResourceView& rv) |
| | | { |
| | | m_issues.clear(); |
| | | |
| | | // 让 add åæ¶æ¯æ const char* å std::string |
| | | auto add = [&](uint32_t code, std::string msg) { |
| | | m_issues.push_back({ code, std::move(msg) }); |
| | | }; |
| | | |
| | | if (!rv.isProcessJobsEmpty()) { |
| | | add(1000, "ProcessJobs Conflict!"); |
| | | } |
| | | |
| | | // ââ åºæ¬ / æ è¯ ââ |
| | | if (m_pjId.empty()) add(1001, "PJID empty"); |
| | | if (!asciiPrintable(m_pjId)) add(1002, "PJID has non-printable chars"); |
| | | |
| | | // if (m_parentCjId.empty()) add(1010, "Parent CJID empty"); |
| | | |
| | | // ââ é
æ¹ï¼RCPSPEC / PPIDï¼ââ |
| | | if (m_recipeSpec.empty()) add(1020, "Recipe spec (PPID) empty"); |
| | | else if (!rv.recipeExists(m_recipeSpec)) { |
| | | add(1021, "PPID not found: " + m_recipeSpec); |
| | | } |
| | | |
| | | // ââ é
æ¹æ¹æ³ vs åæ° ââ 1=NoTuning ç¦æ¢å¸¦åæ°ï¼2=WithTuning å
许/å¯é |
| | | if (m_recipeMethod == RecipeMethod::NoTuning && !m_params.empty()) { |
| | | add(1022, "Params not allowed when PRRECIPEMETHOD=1 (NoTuning)"); |
| | | } |
| | | |
| | | // ââ ç©æéæ©æ ¡éª ââï¼äºéä¸ï¼Carrier+Slots æ MIDsï¼ä¸¤è
é½ä¸å¡«åéè¯¯ï¼ |
| | | const bool hasCarrierSlots = !m_carriers.empty(); |
| | | if (hasCarrierSlots) { |
| | | // {L:n { CARRIERID {L:j SLOTID} }} |
| | | for (const auto& cs : m_carriers) { |
| | | if (cs.carrierId.empty()) { |
| | | add(1030, "CarrierID empty"); |
| | | continue; |
| | | } |
| | | if (!rv.carrierPresent(cs.carrierId)) { |
| | | add(1031, "Carrier not present: " + cs.carrierId); |
| | | } |
| | | if (cs.slots.empty()) { |
| | | add(1032, "No slots specified for carrier: " + cs.carrierId); |
| | | } |
| | | for (auto s : cs.slots) { |
| | | if (s == 0) { |
| | | add(1033, "Slot 0 is invalid for carrier: " + cs.carrierId); |
| | | continue; |
| | | } |
| | | if (!rv.slotUsable(cs.carrierId, s)) { |
| | | add(1034, "Slot unusable: carrier=" + cs.carrierId + " slot=" + std::to_string(s)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | add(1035, "No material selection provided (neither Carrier/Slots nor MIDs)"); |
| | | } |
| | | |
| | | // ââ æåäºä»¶ï¼PRPAUSEEVENTID å表ï¼ââ |
| | | for (auto ceid : m_pauseEvents) { |
| | | if (!rv.ceidDefined(ceid)) { |
| | | add(1050, "Pause CEID unknown: " + std::to_string(ceid)); |
| | | } |
| | | } |
| | | |
| | | return m_issues.empty(); |
| | | } |
| | | |
| | | // ââ ç¶ææº ââ |
| | | // è§åå¯æä½ ä»¬åè®®å¾®è° |
| | | bool CProcessJob::queue() { |
| | | if (m_state != PJState::NoState) return false; |
| | | markQueued(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::enterSettingUp() { |
| | | if (m_state != PJState::Queued) return false; |
| | | m_state = PJState::SettingUp; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::start() { |
| | | if (m_state != PJState::Queued && m_state != PJState::SettingUp && m_state != PJState::Paused) |
| | | return false; |
| | | if (!m_tStart.has_value()) markStart(); |
| | | m_state = PJState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::pause() { |
| | | if (m_state != PJState::InProcess) return false; |
| | | m_state = PJState::Paused; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::resume() { |
| | | if (m_state != PJState::Paused) return false; |
| | | m_state = PJState::InProcess; |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::complete() { |
| | | if (m_state != PJState::InProcess && m_state != PJState::Paused) return false; |
| | | m_state = PJState::Completed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::abort() { |
| | | if (m_state == PJState::Completed || m_state == PJState::Aborted || m_state == PJState::Failed) |
| | | return false; |
| | | m_state = PJState::Aborted; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | bool CProcessJob::fail(std::string reason) { |
| | | m_failReason = trimCopy(reason); |
| | | clampString(m_failReason, 128); |
| | | m_state = PJState::Failed; |
| | | markEnd(); |
| | | return true; |
| | | } |
| | | |
| | | // ââ æ¶é´æ³ & å·¥å
· ââ |
| | | void CProcessJob::markQueued() { |
| | | m_state = PJState::Queued; |
| | | m_tQueued = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::markStart() { |
| | | m_tStart = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::markEnd() { |
| | | m_tEnd = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CProcessJob::clampString(std::string& s, size_t maxLen) { |
| | | if (s.size() > maxLen) s.resize(maxLen); |
| | | } |
| | | |
| | | bool CProcessJob::asciiPrintable(const std::string& s) { |
| | | return std::all_of(s.begin(), s.end(), [](unsigned char c) { |
| | | return c >= 0x20 && c <= 0x7E; |
| | | }); |
| | | } |
| | | |
| | | void CProcessJob::setCarriers(std::vector<CarrierSlotInfo> carriers) |
| | | { |
| | | // ç»ä¸éè¿ addCarrier åè§èåï¼å»ç©ºç½ãæªæãå»éãåå¹¶å carrierï¼ |
| | | m_carriers.clear(); |
| | | m_carriers.reserve(carriers.size()); |
| | | for (auto& cs : carriers) { |
| | | addCarrier(std::move(cs.carrierId), std::move(cs.slots)); |
| | | } |
| | | } |
| | | |
| | | void CProcessJob::addCarrier(std::string carrierId, std::vector<uint8_t> slots) |
| | | { |
| | | // 1) è§èå carrierIdï¼å»ç©ºç½ + é¿åº¦éå¶ |
| | | carrierId = trimCopy(std::move(carrierId)); |
| | | clampString(carrierId, MAX_ID_LEN); |
| | | if (carrierId.empty()) { |
| | | // 空 ID ç´æ¥å¿½ç¥ï¼ä¹å¯ä»¥éæ©æå¼å¸¸/è®°å½æ¥å¿ï¼çä½ é¡¹ç®é£æ ¼ï¼ |
| | | return; |
| | | } |
| | | |
| | | // 2) è§èå slotsï¼å» 0ãæåºãå»é |
| | | // 注ï¼SLOTID æ 1..Nï¼0 è§ä¸ºéæ³/å ä½ |
| | | slots.erase(std::remove(slots.begin(), slots.end(), 0), slots.end()); |
| | | std::sort(slots.begin(), slots.end()); |
| | | slots.erase(std::unique(slots.begin(), slots.end()), slots.end()); |
| | | if (slots.empty()) { |
| | | // æ²¡æææå¡ä½å°±ä¸è¿½å |
| | | return; |
| | | } |
| | | |
| | | // 3) 妿已åå¨ååè½½å
·ï¼ååå¹¶ slot å表 |
| | | auto it = std::find_if(m_carriers.begin(), m_carriers.end(), |
| | | [&](const CarrierSlotInfo& cs) { return cs.carrierId == carrierId; }); |
| | | |
| | | if (it != m_carriers.end()) { |
| | | // åå¹¶ |
| | | it->slots.insert(it->slots.end(), slots.begin(), slots.end()); |
| | | std::sort(it->slots.begin(), it->slots.end()); |
| | | it->slots.erase(std::unique(it->slots.begin(), it->slots.end()), it->slots.end()); |
| | | } |
| | | else { |
| | | // æ°å¢ |
| | | CarrierSlotInfo cs; |
| | | cs.carrierId = std::move(carrierId); |
| | | cs.slots = std::move(slots); |
| | | m_carriers.emplace_back(std::move(cs)); |
| | | } |
| | | } |
| | | |
| | | // --------- æ ¸å¿ï¼serialize/deserialize --------- |
| | | void CProcessJob::serialize(std::ostream& os) const { |
| | | // Í· |
| | | write_pod(os, PJ_FILE_MAGIC); |
| | | write_pod(os, PJ_FILE_VERSION); |
| | | |
| | | // åºæ¬ |
| | | write_string(os, m_pjId); |
| | | write_string(os, m_parentCjId); |
| | | |
| | | // é
æ¹ |
| | | uint8_t recipeType = static_cast<uint8_t>(m_recipeMethod); |
| | | write_pod(os, m_recipeMethod); |
| | | write_string(os, m_recipeSpec); |
| | | |
| | | // ç©æï¼å¤ Carrier & Slotï¼ |
| | | { |
| | | uint32_t n = static_cast<uint32_t>(m_carriers.size()); |
| | | write_pod(os, n); |
| | | for (const auto& cs : m_carriers) { |
| | | write_string(os, cs.carrierId); |
| | | write_vec<uint8_t>(os, cs.slots); |
| | | } |
| | | } |
| | | |
| | | // åæ° |
| | | { |
| | | uint32_t n = static_cast<uint32_t>(m_params.size()); |
| | | write_pod(os, n); |
| | | for (const auto& p : m_params) { |
| | | write_string(os, p.name); |
| | | write_string(os, p.value); |
| | | } |
| | | } |
| | | |
| | | // æåäºä»¶ |
| | | write_vec<uint32_t>(os, m_pauseEvents); |
| | | |
| | | // å¯å¨çç¥ & ç¶æ |
| | | uint8_t startPolicy = static_cast<uint8_t>(m_startPolicy); |
| | | uint8_t st = static_cast<uint8_t>(m_state); |
| | | write_pod(os, startPolicy); |
| | | write_pod(os, st); |
| | | |
| | | // 失败åå |
| | | write_string(os, m_failReason); |
| | | |
| | | // æ¶é´æ³ |
| | | write_opt_time(os, m_tQueued); |
| | | write_opt_time(os, m_tStart); |
| | | write_opt_time(os, m_tEnd); |
| | | } |
| | | |
| | | bool CProcessJob::deserialize(std::istream& is, CProcessJob& out, std::string* err) { |
| | | auto fail = [&](const char* msg) { if (err) *err = msg; return false; }; |
| | | |
| | | uint32_t magic = 0; if (!read_pod(is, magic)) return fail("read magic failed"); |
| | | if (magic != PJ_FILE_MAGIC) return fail("bad magic"); |
| | | |
| | | uint16_t ver = 0; if (!read_pod(is, ver)) return fail("read version failed"); |
| | | if (ver != PJ_FILE_VERSION) return fail("unsupported version"); |
| | | |
| | | // åºæ¬ |
| | | if (!read_string(is, out.m_pjId)) return fail("read pjId"); |
| | | if (!read_string(is, out.m_parentCjId)) return fail("read parentCjId"); |
| | | |
| | | // é
æ¹ |
| | | uint8_t recipeType = 0; if (!read_pod(is, recipeType)) return fail("read recipeType"); |
| | | out.m_recipeMethod = static_cast<RecipeMethod>(recipeType); |
| | | if (!read_string(is, out.m_recipeSpec)) return fail("read recipeSpec"); |
| | | |
| | | // ç©æ |
| | | { |
| | | uint32_t n = 0; if (!read_pod(is, n)) return fail("read carriers count"); |
| | | out.m_carriers.clear(); out.m_carriers.reserve(n); |
| | | for (uint32_t i = 0; i < n; ++i) { |
| | | CarrierSlotInfo cs; |
| | | if (!read_string(is, cs.carrierId)) return fail("read carrierId"); |
| | | if (!read_vec<uint8_t>(is, cs.slots)) return fail("read slots"); |
| | | out.m_carriers.emplace_back(std::move(cs)); |
| | | } |
| | | } |
| | | |
| | | // åæ° |
| | | { |
| | | uint32_t n = 0; if (!read_pod(is, n)) return fail("read params count"); |
| | | out.m_params.clear(); out.m_params.reserve(n); |
| | | for (uint32_t i = 0; i < n; ++i) { |
| | | PJParam p; |
| | | if (!read_string(is, p.name)) return fail("read param name"); |
| | | if (!read_string(is, p.value)) return fail("read param value"); |
| | | out.m_params.emplace_back(std::move(p)); |
| | | } |
| | | } |
| | | |
| | | // æåäºä»¶ |
| | | if (!read_vec<uint32_t>(is, out.m_pauseEvents)) return fail("read pauseEvents"); |
| | | |
| | | // å¯å¨çç¥ & ç¶æ |
| | | uint8_t startPolicy = 0, st = 0; |
| | | if (!read_pod(is, startPolicy)) return fail("read startPolicy"); |
| | | if (!read_pod(is, st)) return fail("read state"); |
| | | out.m_startPolicy = static_cast<StartPolicy>(startPolicy); |
| | | out.m_state = static_cast<PJState>(st); |
| | | |
| | | // 失败åå |
| | | if (!read_string(is, out.m_failReason)) return fail("read failReason"); |
| | | |
| | | // æ¶é´æ³ |
| | | if (!read_opt_time(is, out.m_tQueued)) return fail("read tQueued"); |
| | | if (!read_opt_time(is, out.m_tStart)) return fail("read tStart"); |
| | | if (!read_opt_time(is, out.m_tEnd)) return fail("read tEnd"); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | std::string CProcessJob::getStateText() |
| | | { |
| | | switch (m_state) |
| | | { |
| | | case SERVO::PJState::NoState: |
| | | return "NoState"; |
| | | break; |
| | | case SERVO::PJState::Queued: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::PJState::SettingUp: |
| | | return "SettingUp"; |
| | | break; |
| | | case SERVO::PJState::InProcess: |
| | | return "InProcess"; |
| | | break; |
| | | case SERVO::PJState::Paused: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::PJState::Aborting: |
| | | return "Aborting"; |
| | | break; |
| | | case SERVO::PJState::Completed: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::PJState::Aborted: |
| | | return "Aborted"; |
| | | break; |
| | | case SERVO::PJState::Failed: |
| | | return "Failed"; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | CarrierSlotInfo* CProcessJob::getCarrier(std::string& strId) |
| | | { |
| | | for (auto& item : m_carriers) { |
| | | if (item.carrierId.compare(strId) == 0) { |
| | | return &item; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <string> |
| | | #include <vector> |
| | | #include <unordered_map> |
| | | #include <unordered_set> |
| | | #include <algorithm> |
| | | #include <cstdint> |
| | | #include <chrono> |
| | | #include <optional> |
| | | |
| | | namespace SERVO { |
| | | /// PJ çå½å¨æï¼è´´è¿ E40 常è§ç¶æï¼ |
| | | enum class PJState : uint8_t { |
| | | NoState = 0, |
| | | Queued, |
| | | SettingUp, |
| | | InProcess, |
| | | Paused, |
| | | Aborting, |
| | | Completed, |
| | | Aborted, |
| | | Failed |
| | | }; |
| | | |
| | | /// é
æ¹æå®æ¹å¼ï¼å¯¹åº S16F15 é PRRECIPEMETHODï¼ |
| | | enum class RecipeMethod : uint8_t { |
| | | NoTuning = 1, // 1 - recipe without variable tuning |
| | | WithTuning = 2 // 2 - recipe with variable tuning |
| | | }; |
| | | |
| | | /// å¯å¨çç¥ï¼å¯¹åº S16F15 é PRPROCESSSTARTï¼ |
| | | enum class StartPolicy : uint8_t { |
| | | Queued = 0, // 建ç«åæé |
| | | AutoStart = 1 // æ¡ä»¶æ»¡è¶³åèªå¨å¯å¨ |
| | | }; |
| | | |
| | | /** é
æ¹åæ°å¯¹ï¼S16F15 ä¸ RCPPARNM / RCPPARVALï¼ */ |
| | | struct PJParam { |
| | | std::string name; // RCPPARNM |
| | | std::string value; // RCPPARVAL |
| | | }; |
| | | |
| | | /** |
| | | {L:2 |
| | | CARRIERID |
| | | {L:j |
| | | SLOTID |
| | | } |
| | | } |
| | | */ |
| | | struct CarrierSlotInfo { |
| | | std::string carrierId; // CARRIERID |
| | | std::vector<uint8_t> slots; // SLOTID[] |
| | | std::vector<void*> contexts; // Glass |
| | | }; |
| | | |
| | | /// ç®åèµæºè§å¾æ¥å£ï¼ä¾ Validate() æ¥è¯¢ï¼ç±è®¾å¤ç«¯å®ç°è
å¨å¤é¨æä¾ï¼ |
| | | struct IResourceView { |
| | | virtual ~IResourceView() = default; |
| | | virtual bool isProcessJobsEmpty() const = 0; |
| | | virtual bool recipeExists(const std::string& ppid) const = 0; |
| | | virtual bool carrierPresent(const std::string& carrierId) const = 0; |
| | | virtual bool slotUsable(const std::string& carrierId, uint16_t slot) const = 0; |
| | | virtual bool ceidDefined(uint32_t ceid) const = 0; |
| | | // ä½ ä¹å¯ä»¥æ©å±ï¼portç¶æãå ç¨æ
åµãCJ/PJ空é´ç |
| | | }; |
| | | |
| | | /// PJ 主类 |
| | | /** |
| | | * ProcessJob ââ ä¸ S16F15ï¼PRJobMultiCreateï¼å段ä¸ä¸å¯¹åºçæ¿è½½ç±» |
| | | * |
| | | * S16F15 ç»æï¼æ ¸å¿èéï¼ï¼ |
| | | * {L:6 |
| | | * PRJOBID -> m_pjId |
| | | * MF -> m_mf |
| | | * {L:n { CARRIERID {L:j SLOTID} } } |
| | | * {L:3 |
| | | * PRRECIPEMETHOD -> m_recipeType |
| | | * RCPSPECï¼PPIDï¼ -> m_recipeSpec |
| | | * {L:m { RCPPARNM RCPPARVAL }} -> m_params |
| | | * } |
| | | * PRPROCESSSTART -> m_startPolicy |
| | | * {L:k PRPAUSEEVENTID} -> m_pauseEvents |
| | | * } |
| | | */ |
| | | class CProcessJob { |
| | | public: |
| | | // ââ æé / åºæ¬è®¾ç½® ââ |
| | | CProcessJob(); |
| | | explicit CProcessJob(std::string pjId); |
| | | |
| | | const std::string& id() const noexcept { return m_pjId; } |
| | | const std::string& parentCjId() const noexcept { return m_parentCjId; } |
| | | PJState state() const noexcept { return m_state; } |
| | | StartPolicy startPolicy() const noexcept { return m_startPolicy; } |
| | | RecipeMethod recipeMethod() const noexcept { return m_recipeMethod; } |
| | | const std::string& recipeSpec() const noexcept { return m_recipeSpec; } // PPID æ Spec |
| | | std::string getStateText(); |
| | | |
| | | // ç»å®ç¶ CJ |
| | | void setParentCjId(std::string cjId); |
| | | |
| | | // é
æ¹ |
| | | void setRecipe(RecipeMethod method, std::string spec); |
| | | |
| | | // å¯å¨çç¥ |
| | | void setStartPolicy(StartPolicy sp) { m_startPolicy = sp; } |
| | | |
| | | // åæ° |
| | | void addParam(std::string name, std::string value); |
| | | void setParams(std::vector<PJParam> params); |
| | | |
| | | // æåäºä»¶ |
| | | void addPauseEvent(uint32_t ceid); |
| | | void setPauseEvents(std::vector<uint32_t> ceids); |
| | | |
| | | // ââ æ ¡éª ââ |
| | | struct ValidationIssue { |
| | | uint32_t code; // èªå®ä¹é误ç |
| | | std::string text; // ææ¬æè¿° |
| | | }; |
| | | // è¿åé®é¢æ¸
åï¼ç©º=éè¿ï¼ |
| | | bool validate(const IResourceView& rv); |
| | | const std::vector<ValidationIssue>& issues(); |
| | | |
| | | // ââ ç¶ææºï¼å¸¦å®å«ï¼ââ |
| | | bool queue(); // NoState -> Queued |
| | | bool start(); // Queued/SettingUp -> InProcess |
| | | bool enterSettingUp(); // Queued -> SettingUp |
| | | bool pause(); // InProcess -> Paused |
| | | bool resume(); // Paused -> InProcess |
| | | bool complete(); // InProcess -> Completed |
| | | bool abort(); // Any (æªç»æ) -> Aborted |
| | | bool fail(std::string reason); // ä»»ææ -> Failedï¼è®°å½å¤±è´¥åå ï¼ |
| | | |
| | | // ââ 访é®å¨ï¼ç¨äºä¸æ¥/æ¥è¯¢ï¼ââ |
| | | const std::vector<PJParam>& params() const noexcept { return m_params; } |
| | | const std::vector<uint32_t>& pauseEvents() const noexcept { return m_pauseEvents; } |
| | | 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; } |
| | | |
| | | // é¿åº¦éå¶å·¥å
·ï¼å¯å¨éææ¶ç»ä¸çç¥ï¼ |
| | | static void clampString(std::string& s, size_t maxLen); |
| | | static bool asciiPrintable(const std::string& s); |
| | | |
| | | // æ¸
空并æ´ä½è®¾ç½® |
| | | void setCarriers(std::vector<CarrierSlotInfo> carriers); |
| | | |
| | | // 追å ä¸ä¸ªè½½å
· |
| | | void addCarrier(std::string carrierId, std::vector<uint8_t> slots); |
| | | |
| | | // 访é®å¨ |
| | | const std::vector<CarrierSlotInfo>& carriers() const noexcept { return m_carriers; } |
| | | CarrierSlotInfo* getCarrier(std::string& strId); |
| | | |
| | | // å¤å®æ¯å¦âæè½½å
·/å¡ä½âæ¹å¼ |
| | | bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); } |
| | | |
| | | |
| | | public: |
| | | // ====== çæ¬å¤´å¸¸éï¼å»ºè®®ä¿çï¼ä¾¿äºå
¼å®¹ï¼====== |
| | | static constexpr uint32_t PJ_FILE_MAGIC = 0x504A4A31; // "PJJ1" |
| | | static constexpr uint16_t PJ_FILE_VERSION = 0x0001; |
| | | |
| | | // ====== æµå¼åºååæ¥å£ ====== |
| | | void serialize(std::ostream& os) const; |
| | | static bool deserialize(std::istream& is, CProcessJob& out, std::string* err = nullptr); |
| | | |
| | | private: |
| | | // å
é¨ç¶æè½¬ç§»å¸®å© |
| | | void markQueued(); |
| | | void markStart(); |
| | | void markEnd(); |
| | | |
| | | private: |
| | | // æ è¯ |
| | | std::string m_pjId; |
| | | std::string m_parentCjId; |
| | | |
| | | // é
æ¹ |
| | | RecipeMethod m_recipeMethod{ RecipeMethod::NoTuning }; |
| | | std::string m_recipeSpec; // PPID / Spec |
| | | |
| | | // ç©æ |
| | | static constexpr uint8_t MATERIAL_FORMAT = 14; // substrate |
| | | std::vector<CarrierSlotInfo> m_carriers; // {L:n { CARRIERID {L:j SLOTID} }} |
| | | |
| | | // åæ° / æåäºä»¶ |
| | | std::vector<PJParam> m_params; |
| | | std::vector<uint32_t> m_pauseEvents; |
| | | |
| | | // ç¶æ & è®°å½ |
| | | StartPolicy m_startPolicy{ StartPolicy::Queued }; // 0=Queued, 1=AutoStart |
| | | PJState m_state{ PJState::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; // PJID/ CJID/ CarrierID/ MID/ PPID |
| | | static constexpr size_t MAX_PARAM_K = 32; // åæ°å |
| | | static constexpr size_t MAX_PARAM_V = 64; // åæ°å¼ |
| | | |
| | | // é误å表 |
| | | std::vector<ValidationIssue> m_issues; |
| | | }; |
| | | } |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <fstream> |
| | | |
| | | |
| | | // --------- ç§æ/å
é¨ï¼è¯»åå·¥å
· --------- |
| | | namespace SERVO { |
| | | template<typename T> |
| | | inline void write_pod(std::ostream& os, const T& v) { |
| | | os.write(reinterpret_cast<const char*>(&v), sizeof(T)); |
| | | } |
| | | template<typename T> |
| | | inline bool read_pod(std::istream& is, T& v) { |
| | | return bool(is.read(reinterpret_cast<char*>(&v), sizeof(T))); |
| | | } |
| | | |
| | | inline void write_string(std::ostream& os, const std::string& s) { |
| | | uint32_t n = static_cast<uint32_t>(s.size()); |
| | | write_pod(os, n); |
| | | if (n) os.write(s.data(), n); |
| | | } |
| | | inline bool read_string(std::istream& is, std::string& s) { |
| | | uint32_t n = 0; if (!read_pod(is, n)) return false; |
| | | s.resize(n); |
| | | if (n) return bool(is.read(&s[0], n)); |
| | | return true; |
| | | } |
| | | |
| | | template<typename T> |
| | | inline void write_vec(std::ostream& os, const std::vector<T>& v) { |
| | | uint32_t n = static_cast<uint32_t>(v.size()); |
| | | write_pod(os, n); |
| | | if (n) os.write(reinterpret_cast<const char*>(v.data()), sizeof(T) * n); |
| | | } |
| | | template<typename T> |
| | | inline bool read_vec(std::istream& is, std::vector<T>& v) { |
| | | uint32_t n = 0; if (!read_pod(is, n)) return false; |
| | | v.resize(n); |
| | | if (n) return bool(is.read(reinterpret_cast<char*>(v.data()), sizeof(T) * n)); |
| | | return true; |
| | | } |
| | | |
| | | // vector<string> ç¹åå读 |
| | | inline void write_vec_str(std::ostream& os, const std::vector<std::string>& v) { |
| | | uint32_t n = static_cast<uint32_t>(v.size()); |
| | | write_pod(os, n); |
| | | for (const auto& s : v) write_string(os, s); |
| | | } |
| | | inline bool read_vec_str(std::istream& is, std::vector<std::string>& v) { |
| | | uint32_t n = 0; if (!read_pod(is, n)) return false; |
| | | v.clear(); v.reserve(n); |
| | | for (uint32_t i = 0; i < n; ++i) { std::string s; if (!read_string(is, s)) return false; v.emplace_back(std::move(s)); } |
| | | return true; |
| | | } |
| | | |
| | | // optional<time_point> â bool + int64 (ms since epoch) |
| | | inline void write_opt_time(std::ostream& os, const std::optional<std::chrono::system_clock::time_point>& tp) { |
| | | uint8_t has = tp.has_value() ? 1 : 0; |
| | | write_pod(os, has); |
| | | if (has) { |
| | | auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp->time_since_epoch()).count(); |
| | | int64_t v = static_cast<int64_t>(ms); |
| | | write_pod(os, v); |
| | | } |
| | | } |
| | | inline bool read_opt_time(std::istream& is, std::optional<std::chrono::system_clock::time_point>& tp) { |
| | | uint8_t has = 0; if (!read_pod(is, has)) return false; |
| | | if (!has) { tp.reset(); return true; } |
| | | int64_t v = 0; if (!read_pod(is, v)) return false; |
| | | tp = std::chrono::system_clock::time_point(std::chrono::milliseconds(v)); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <SDLCheck>true</SDLCheck> |
| | | <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;..\MELSECSDK\include;.\CCLinkPerformance;.\GridControl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| | | <LanguageStandard>stdcpp17</LanguageStandard> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Windows</SubSystem> |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="CBaseDlg.h" /> |
| | | <ClInclude Include="CControlJob.h" /> |
| | | <ClInclude Include="CControlJobDlg.h" /> |
| | | <ClInclude Include="CCustomCheckBox.h" /> |
| | | <ClInclude Include="CCollectionEvent.h" /> |
| | | <ClInclude Include="CEquipmentPage3.h" /> |
| | | <ClInclude Include="CExpandableListCtrl.h" /> |
| | | <ClInclude Include="CGlassPool.h" /> |
| | | <ClInclude Include="ChangePasswordDlg.h" /> |
| | | <ClInclude Include="CMyStatusbar.h" /> |
| | |
| | | <ClInclude Include="PageRobotCmd.h" /> |
| | | <ClInclude Include="PageTransferLog.h" /> |
| | | <ClInclude Include="PortConfigurationDlg.h" /> |
| | | <ClInclude Include="ProcessJob.h" /> |
| | | <ClInclude Include="ProductionLogManager.h" /> |
| | | <ClInclude Include="RecipeDeviceBindDlg.h" /> |
| | | <ClInclude Include="RecipeManager.h" /> |
| | | <ClInclude Include="Resource.h" /> |
| | | <ClInclude Include="SECSRuntimeManager.h" /> |
| | | <ClInclude Include="SecsTestDlg.h" /> |
| | | <ClInclude Include="SerializeUtil.h" /> |
| | | <ClInclude Include="Servo.h" /> |
| | | <ClInclude Include="ServoCommo.h" /> |
| | | <ClInclude Include="ServoDlg.h" /> |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="CBaseDlg.cpp" /> |
| | | <ClCompile Include="CControlJob.cpp" /> |
| | | <ClCompile Include="CControlJobDlg.cpp" /> |
| | | <ClCompile Include="CCustomCheckBox.cpp" /> |
| | | <ClCompile Include="CCollectionEvent.cpp" /> |
| | | <ClCompile Include="CEquipmentPage3.cpp" /> |
| | | <ClCompile Include="CExpandableListCtrl.cpp" /> |
| | | <ClCompile Include="CGlassPool.cpp" /> |
| | | <ClCompile Include="ChangePasswordDlg.cpp" /> |
| | | <ClCompile Include="CMyStatusbar.cpp" /> |
| | |
| | | <ClCompile Include="PageRobotCmd.cpp" /> |
| | | <ClCompile Include="PageTransferLog.cpp" /> |
| | | <ClCompile Include="PortConfigurationDlg.cpp" /> |
| | | <ClCompile Include="ProcessJob.cpp" /> |
| | | <ClCompile Include="ProductionLogManager.cpp" /> |
| | | <ClCompile Include="RecipeDeviceBindDlg.cpp" /> |
| | | <ClCompile Include="RecipeManager.cpp" /> |
| | |
| | | <ClCompile Include="CPageVarialbles.cpp" /> |
| | | <ClCompile Include="CPageReport.cpp" /> |
| | | <ClCompile Include="CPageCollectionEvent.cpp" /> |
| | | <ClCompile Include="ProcessJob.cpp" /> |
| | | <ClCompile Include="CControlJob.cpp" /> |
| | | <ClCompile Include="CExpandableListCtrl.cpp" /> |
| | | <ClCompile Include="CControlJobDlg.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | <ClInclude Include="CPageVarialbles.h" /> |
| | | <ClInclude Include="CPageReport.h" /> |
| | | <ClInclude Include="CPageCollectionEvent.h" /> |
| | | <ClInclude Include="ProcessJob.h" /> |
| | | <ClInclude Include="CControlJob.h" /> |
| | | <ClInclude Include="SerializeUtil.h" /> |
| | | <ClInclude Include="CExpandableListCtrl.h" /> |
| | | <ClInclude Include="CControlJobDlg.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |
| | |
| | | #include "CPageVarialbles.h" |
| | | #include "CPageReport.h" |
| | | #include "CPageCollectionEvent.h" |
| | | #include "CControlJobDlg.h" |
| | | |
| | | |
| | | #ifdef _DEBUG |
| | |
| | | /* è¿è¡æ¶é´å®æ¶å¨ */ |
| | | #define TIMER_ID_UPDATE_RUMTIME 2 |
| | | |
| | | /* Test */ |
| | | #define TIMER_ID_TEST 3 |
| | | |
| | | |
| | | // ç¨äºåºç¨ç¨åºâå
³äºâèå项ç CAboutDlg å¯¹è¯æ¡ |
| | |
| | | |
| | | // model init |
| | | theApp.m_model.init(); |
| | | |
| | | SetTimer(TIMER_ID_TEST, 1000, nullptr); |
| | | |
| | | // èå |
| | | CMenu menu; |
| | |
| | | HMENU hMenu = m_pTopToolbar->GetOperatorMenu(); |
| | | ASSERT(hMenu); |
| | | ::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); |
| | | |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_JOBS)->EnableWindow(TRUE); |
| | | |
| | | |
| | | // Tab |
| | | m_pPageGraph1 = new CPageGraph1(); |
| | |
| | | m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText); |
| | | } |
| | | |
| | | else if(TIMER_ID_TEST == nIDEvent){ |
| | | static __int64 tttt = 0; |
| | | tttt++; |
| | | theApp.m_model.m_hsmsPassive.setVariableValue("CJobSpace", tttt % 10); |
| | | theApp.m_model.m_hsmsPassive.setVariableValue("PJobSpace", tttt % 5); |
| | | } |
| | | |
| | | |
| | | CDialogEx::OnTimer(nIDEvent); |
| | | } |
| | |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE); |
| | | } |
| | | } |
| | | else if (id == IDC_BUTTON_JOBS) { |
| | | CControlJobDlg dlg; |
| | | dlg.SetControlJob(theApp.m_model.m_master.getControlJob()); |
| | | dlg.DoModal(); |
| | | } |
| | | else if (id == IDC_BUTTON_PORT_CONFIG) { |
| | | CPortConfigurationDlg dlg; |
| | | dlg.DoModal(); |
| | |
| | | DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun); |
| | | DDX_Control(pDX, IDC_BUTTON_RUN_CT, m_btnRunCt); |
| | | DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop); |
| | | DDX_Control(pDX, IDC_BUTTON_JOBS, m_btnCJobs); |
| | | DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm); |
| | | DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings); |
| | | DDX_Control(pDX, IDC_BUTTON_PORT_CONFIG, m_btnPortConfig); |
| | |
| | | InitBtn(m_btnRunCt, "RunCt_High_32.ico", "RunCt_Gray_32.ico"); |
| | | InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico"); |
| | | InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico"); |
| | | InitBtn(m_btnCJobs, "ControlJob_High_32.ico", "ControlJob_Gray_32.ico"); |
| | | InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico"); |
| | | InitBtn(m_btnRobot, "Robot_High_32.ico", "Robot_Gray_32.ico"); |
| | | InitBtn(m_btnPortConfig, "PortConfig_High_32.ico", "PortConfig_Gray_32.ico"); |
| | |
| | | x += 2; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_STOP); |
| | | pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight); |
| | | x += BTN_WIDTH; |
| | | x += 2; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_JOBS); |
| | | pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight); |
| | | x += BTN_WIDTH; |
| | | x += 2; |
| | |
| | | case IDC_BUTTON_RUN: |
| | | case IDC_BUTTON_RUN_CT: |
| | | case IDC_BUTTON_STOP: |
| | | case IDC_BUTTON_JOBS: |
| | | case IDC_BUTTON_ALARM: |
| | | case IDC_BUTTON_SETTINGS: |
| | | case IDC_BUTTON_PORT_CONFIG: |
| | |
| | | CBlButton m_btnRun; |
| | | CBlButton m_btnRunCt; |
| | | CBlButton m_btnStop; |
| | | CBlButton m_btnCJobs; |
| | | CBlButton m_btnAlarm; |
| | | CBlButton m_btnSettings; |
| | | CBlButton m_btnPortConfig; |
| | |
| | | 40000,E90_SPSM_NoState_To_NeedsProcessing,,(40000) |
| | | 40001,E90_SPSM_InProcess_To_ProcessCompleted,,(40000) |
| | | 50000,CarrierID_Readed,,(50000) |
| | | 50001,PJ_Queued,,(50001) |
| | |
| | | 31000,(1,31000,31001) |
| | | 40000,(1,10203,20000) |
| | | 50000,(5000) |
| | | 50001,(5003) |
| | | |
| | |
| | | 701,PreviousProcessState,U1, |
| | | 800,EFEMPPExecName,A20, |
| | | 801,EQPPExecName,A20, |
| | | 1000,CJobSpace,U1, |
| | | 2000,RbRAxisTorque,I2,æºå¨äººRè½´æç© |
| | | 2001,RbLAxisTorque,l2,æºå¨äººLè½´æç© |
| | | 2002,RbZAxisTorque,l2,æºå¨äººZè½´æç© |
| | |
| | | 2024,CCDEnable,U2,"CCD使è½ï¼O:å¼å¯ 1ï¼å±è½" |
| | | 2025,FFUParameter,U2,FFU设å®å¼ |
| | | 5000,CarrierID,A20,å¡å£ID |
| | | 5001,CJobSpace,U1,CJ Space |
| | | 5002,PJobSpace,U1,PJ Space |
| | | 5003,PJQueued,L,PJ Queued |