From 72f3802bd7ab24b672c951a287787b5dea253f3b Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期六, 02 八月 2025 10:48:36 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/Servo/CPageGraph2.cpp | 5
SourceCode/Bond/Servo/HsmsPassive.h | 8
SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico | 0
SourceCode/Bond/Servo/resource.h | 0
SourceCode/Bond/EAPSimulator/CHsmsActive.h | 4
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h | 2
SourceCode/Bond/Servo/HsmsPassive.cpp | 238 +++++++++++++++++++----
SourceCode/Bond/EAPSimulator/EAPSimulator.rc | 0
SourceCode/Bond/Servo/CMaster.h | 5
SourceCode/Bond/Servo/Model.cpp | 3
SourceCode/Bond/Servo/ServoDlg.cpp | 20 +
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp | 25 ++
SourceCode/Bond/EAPSimulator/Resource.h | 2
SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h | 1
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp | 14 +
SourceCode/Bond/Servo/TopToolbar.h | 1
SourceCode/Bond/Servo/CEquipment.cpp | 31 +++
SourceCode/Bond/Servo/Servo.rc | 0
SourceCode/Bond/Servo/TopToolbar.cpp | 8
SourceCode/Bond/Servo/CMaster.cpp | 174 +++++++++++++++++
SourceCode/Bond/Servo/CEquipment.h | 2
SourceCode/Bond/Servo/HsmsAction.cpp | 2
SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico | 0
Document/Panel Bonder八零联合 SecsTest CheckList_v3.0.xlsx | 0
24 files changed, 494 insertions(+), 51 deletions(-)
diff --git "a/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx" "b/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
index 6b16c1a..48e2a37 100644
--- "a/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
+++ "b/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
Binary files differ
diff --git a/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp b/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
index 6d74a5c..96ed8dd 100644
--- a/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
+++ b/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
@@ -67,7 +67,7 @@
LOGI("onRecvDataMessage(%s).", pMessage->toString());
if (nStream == 5 && pHeader->function == 1) {
- // S1F1
+ // S5F1
replyAck(5, 2, pMessage->getHeader()->systemBytes, 0, _T("ACK0"));
}
};
@@ -266,6 +266,29 @@
return 0;
}
+int CHsmsActive::hsmsTransmitSpooledData()
+{
+ IMessage* pMessage = nullptr;
+ int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 23, ++m_nSystemByte);
+ pMessage->getBody()->setU1(0, "RSDC");
+ m_pActive->sendMessage(pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return 0;
+}
+
+int CHsmsActive::hsmsPurgeSpooledData()
+{
+ IMessage* pMessage = nullptr;
+ int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 23, ++m_nSystemByte);
+
+ pMessage->getBody()->setU1(1, "RSDC");
+ m_pActive->sendMessage(pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return 0;
+}
+
int CHsmsActive::replyAck0(IMessage* pMessage)
{
return 0;
diff --git a/SourceCode/Bond/EAPSimulator/CHsmsActive.h b/SourceCode/Bond/EAPSimulator/CHsmsActive.h
index e171c75..7a93948 100644
--- a/SourceCode/Bond/EAPSimulator/CHsmsActive.h
+++ b/SourceCode/Bond/EAPSimulator/CHsmsActive.h
@@ -57,6 +57,10 @@
// Configure Spooling
int hsmsConfigureSpooling(std::map<unsigned int, std::set<unsigned int>>& spoolingConfig);
+ // 发送或清空缓存的消息
+ int hsmsTransmitSpooledData();
+ int hsmsPurgeSpooledData();
+
// 通过的reply函数
void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName);
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.rc b/SourceCode/Bond/EAPSimulator/EAPSimulator.rc
index e90e25a..b126259 100644
--- a/SourceCode/Bond/EAPSimulator/EAPSimulator.rc
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.rc
Binary files differ
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
index 430a1ae..c3c4fb7 100644
--- a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
@@ -85,6 +85,8 @@
ON_BN_CLICKED(IDC_BUTTON_DEFINE_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonDefineReport)
ON_BN_CLICKED(IDC_BUTTON_LINE_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonLineReport)
ON_BN_CLICKED(IDC_BUTTON_CONFIGURE_SPOOLING, &CEAPSimulatorDlg::OnBnClickedButtonConfigureSpooling)
+ ON_BN_CLICKED(IDC_BUTTON_TRANSMIT_SPOOLED_DATA, &CEAPSimulatorDlg::OnBnClickedButtonTransmitSpooledData)
+ ON_BN_CLICKED(IDC_BUTTON_PURGE_SPOOLED_DATA, &CEAPSimulatorDlg::OnBnClickedButtonPurgeSpooledData)
END_MESSAGE_MAP()
@@ -269,6 +271,8 @@
GetDlgItem(IDC_BUTTON_DEFINE_REPORT)->EnableWindow(enabled);
GetDlgItem(IDC_BUTTON_LINE_REPORT)->EnableWindow(enabled);
GetDlgItem(IDC_BUTTON_CONFIGURE_SPOOLING)->EnableWindow(enabled);
+ GetDlgItem(IDC_BUTTON_TRANSMIT_SPOOLED_DATA)->EnableWindow(enabled);
+ GetDlgItem(IDC_BUTTON_PURGE_SPOOLED_DATA)->EnableWindow(enabled);
}
void CEAPSimulatorDlg::OnBnClickedButtonConnect()
@@ -355,3 +359,13 @@
spoolingConfig[5].insert(66);
theApp.m_model.m_pHsmsActive->hsmsConfigureSpooling(spoolingConfig);
}
+
+void CEAPSimulatorDlg::OnBnClickedButtonTransmitSpooledData()
+{
+ theApp.m_model.m_pHsmsActive->hsmsTransmitSpooledData();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonPurgeSpooledData()
+{
+ theApp.m_model.m_pHsmsActive->hsmsPurgeSpooledData();
+}
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
index dd2de49..adc1a71 100644
--- a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
@@ -54,4 +54,6 @@
afx_msg void OnBnClickedButtonDefineReport();
afx_msg void OnBnClickedButtonLineReport();
afx_msg void OnBnClickedButtonConfigureSpooling();
+ afx_msg void OnBnClickedButtonTransmitSpooledData();
+ afx_msg void OnBnClickedButtonPurgeSpooledData();
};
diff --git a/SourceCode/Bond/EAPSimulator/Resource.h b/SourceCode/Bond/EAPSimulator/Resource.h
index fda0a5c..f8b9864 100644
--- a/SourceCode/Bond/EAPSimulator/Resource.h
+++ b/SourceCode/Bond/EAPSimulator/Resource.h
@@ -32,7 +32,9 @@
#define IDC_BUTTON_LINE_REPORT2 1012
#define IDC_BUTTON_CONFIGURE_SPOOLING 1012
#define IDC_RADIO_DISABLE 1013
+#define IDC_BUTTON_TRANSMIT_SPOOLED_DATA 1013
#define IDC_EDIT_CEID 1014
+#define IDC_BUTTON_PURGE_SPOOLED_DATA 1014
#define IDC_LIST1 1015
#define IDC_EDIT_CE_NAME 1015
#define IDC_LIST2 1016
diff --git a/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h b/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
index ba3f21d..b3bfa28 100644
--- a/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
+++ b/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
@@ -69,5 +69,6 @@
virtual ISECS2Item* addU1Item(unsigned char value, const char* pszNote) = 0;
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 ISECS2Item* addItem() = 0;
};
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index 0d99db6..322923d 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -1292,6 +1292,21 @@
return nullptr;
}
+ CSlot* CEquipment::isSlotAvailable(unsigned int slot)
+ {
+ if (slot >= 8) return nullptr;
+ if (!m_slot[slot].isEnable()) return nullptr;
+ if (m_slot[slot].isLock()) return nullptr;
+ if (!m_slot[slot].isEmpty()) return nullptr;
+ int lsPath = m_slot[slot].getLinkSignalPath();
+ if (!m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_INLINE]
+ || m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_TROUBLE]
+ || !m_bLinkSignalToDownstream[lsPath][SIGNAL_INTERLOCK]
+ || !m_bLinkSignalToDownstream[lsPath][SIGNAL_RECEIVE_ABLE]) return nullptr;
+
+ return &m_slot[slot];
+ }
+
CSlot* CEquipment::getNonEmptySlot(MaterialsType putSlotType)
{
for (int i = 0; i < SLOT_MAX; i++) {
@@ -1364,6 +1379,22 @@
return nullptr;
}
+ CSlot* CEquipment::getProcessedSlotCt(unsigned int slot)
+ {
+ if (slot >= 8) return nullptr;
+ if (!m_slot[slot].isEnable()) return nullptr;
+ if (m_slot[slot].isLock()) return nullptr;
+ CGlass* pGlass = (CGlass*)m_slot[slot].getContext();
+ if (pGlass == nullptr) return nullptr;
+ int lsPath = m_slot[slot].getLinkSignalPath();
+ if (!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
+ || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE]
+ || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK]
+ || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE]) return nullptr;
+
+ return &m_slot[slot];
+ }
+
CSlot* CEquipment::getInspFailSlot()
{
for (int i = 0; i < SLOT_MAX; i++) {
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 28bf252..ce75a56 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -176,6 +176,7 @@
// 获取一个指定物料类型(G1,G2,G1&G2)的空槽位
CSlot* getAvailableSlotForGlass(MaterialsType type);
CSlot* getAvailableSlotForGlassExcludeSignal(MaterialsType type);
+ CSlot* isSlotAvailable(unsigned int slot);
// 在指定的槽列表中,获取一个指定物料类型(G1,G2,G1&G2)的空槽位
CSlot* getAvailableSlotForGlass2(MaterialsType type, const std::vector<int>& candidates);
@@ -187,6 +188,7 @@
CSlot* getProcessedSlot(MaterialsType putSlotType);
CSlot* getProcessedSlot2(MaterialsType putSlotType, const std::vector<int>& candidates);
CSlot* getInspFailSlot();
+ CSlot* getProcessedSlotCt(unsigned int slot);
// 获取玻璃物料
CGlass* getGlassFromSlot(int slotNo);
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 6bcda0c..6714999 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -54,6 +54,7 @@
m_isCompareMapsBeforeProceeding = FALSE;
m_bEnableEventReport = true;
m_bEnableAlarmReport = true;
+ m_bContinuousTransfer = false;
InitializeCriticalSection(&m_criticalSection);
}
@@ -251,6 +252,20 @@
return -1;
}
+ m_bContinuousTransfer = false;
+ setState(MASTERSTATE::STARTING);
+ m_ullStartTime = GetTickCount64();
+
+ return 0;
+ }
+
+ int CMaster::startContinuousTransfer()
+ {
+ if (m_state != MASTERSTATE::READY) {
+ return -1;
+ }
+
+ m_bContinuousTransfer = true;
setState(MASTERSTATE::STARTING);
m_ullStartTime = GetTickCount64();
@@ -260,7 +275,7 @@
int CMaster::stop()
{
// 运行时间为累加结果,本次停止时刷新;
- if (m_state != MASTERSTATE::RUNNING) {
+ if (m_state != MASTERSTATE::RUNNING && m_state != MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
return -1;
}
@@ -447,7 +462,11 @@
unlock();
- setState(MASTERSTATE::RUNNING);
+ if(!m_bContinuousTransfer)
+ setState(MASTERSTATE::RUNNING);
+ else
+ setState(MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER);
+
continue;
}
@@ -664,6 +683,132 @@
unlock();
continue;
}
+
+ // 千传模式调度逻辑
+ else if (m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
+ // 检测判断robot状态
+ RMDATA& rmd = pEFEM->getRobotMonitoringData();
+ if (rmd.status != ROBOT_STATUS::Idle && rmd.status != ROBOT_STATUS::Run) {
+ unlock();
+ continue;
+ }
+
+ if (m_pActiveRobotTask != nullptr) {
+ if (m_pActiveRobotTask->isPicked()) {
+ m_pActiveRobotTask->place();
+ }
+ unlock();
+ // 检测到当前有正在下午的任务,确保当前任务完成或中止后继续
+ // LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
+ continue;
+ }
+
+ // Measurement -> LoadPort
+ for (int s = 0; s < 4; s++) {
+ PortType pt = pLoadPorts[s]->getPortType();
+ if (!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) {
+ goto CT_PORT_PUT;
+ }
+ }
+ }
+ }
+
+ CT_PORT_PUT:
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+
+
+ // BakeCooling ->Measurement
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
+ 3, pMeasurement, 0);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+
+ // BakeCooling内部
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
+ 2, pBakeCooling, 3);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
+ 1, pBakeCooling, 2);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
+ 0, pBakeCooling, 1);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+ // Bonder2 -> BakeCooling
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder2,
+ 0, pBakeCooling, 0);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+ // Bonder1 -> Bonder2
+ if (!rmd.armState[0] && !pBonder2->hasBondClass()) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder1,
+ 0, pBonder2, 0);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+ // VacuumBake(G1) -> Bonder1
+ if (!rmd.armState[0] && !pBonder1->hasBondClass()) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pVacuumBake,
+ 0, pBonder1, 0);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+ // Fliper(G2) -> VacuumBake(G1)
+ if (!rmd.armState[0]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pFliper,
+ 0, pVacuumBake, 0);
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+ }
+
+ // Aligner -> Fliper(G2)
+ if (!rmd.armState[1]) {
+ m_pActiveRobotTask = createTransferTask_continuous_transfer(pAligner,
+ 0, pFliper, 0);
+ 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()
+ && (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) {
+ pEFEM->setContext(m_pActiveRobotTask->getContext());
+ goto CT_PORT_GET;
+ }
+ }
+ }
+ }
+
+ CT_PORT_GET:
+ CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
+
+
+ unlock();
+ continue;
+ }
+
+
unlock();
}
@@ -1426,6 +1571,31 @@
return pTask;
}
+ CRobotTask* CMaster::createTransferTask_continuous_transfer(CEquipment* pSrcEq, int nSrcSlot,
+ CEquipment* pTarEq, int nTarSlot, int armNo/* = 1*/)
+ {
+ if (!pSrcEq->IsEnabled()) {
+ return nullptr;
+ }
+ if (!pTarEq->IsEnabled()) {
+ return nullptr;
+ }
+
+ CRobotTask* pTask = nullptr;
+ CSlot* pTarSlot = pTarEq->isSlotAvailable(nTarSlot);
+ CSlot* pSrcSlot = pSrcEq->getProcessedSlotCt(nSrcSlot);
+ if (pSrcSlot != nullptr && nullptr != pTarSlot) {
+ pTask = new CRobotTask();
+ pTask->setContext(pSrcSlot->getContext());
+ pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
+ taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, armNo, pSrcSlot->getPosition(),
+ pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
+ }
+
+
+ return pTask;
+ }
+
int CMaster::abortCurrentTask()
{
lock();
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 76d52eb..7b16db8 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -20,6 +20,7 @@
READY = 0,
STARTING,
RUNNING,
+ RUNNING_CONTINUOUS_TRANSFER,
STOPPING,
MSERROR
};
@@ -57,6 +58,7 @@
int init();
int term();
int start();
+ int startContinuousTransfer();
int stop();
void clearError();
ULONGLONG getRunTime();
@@ -107,6 +109,8 @@
CRobotTask* createTransferTask_bake_to_cooling(CEquipment* pSrcEq);
CRobotTask* createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq);
CRobotTask* createTransferTask_restore(CEquipment* pEqSrc, CLoadPort** pPorts);
+ CRobotTask* createTransferTask_continuous_transfer(CEquipment* pSrcEq, int nSrcSlot,
+ CEquipment* pTarEq, int nTarSlot, int armNo = 1);
private:
CRITICAL_SECTION m_criticalSection;
@@ -115,6 +119,7 @@
std::list<CEquipment*> m_listEquipment;
std::string m_strFilepath;
BOOL m_bDataModify;
+ bool m_bContinuousTransfer;
private:
/* 监控比特位的线程*/
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index a248cf4..cb4d449 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -284,7 +284,10 @@
}
*/
- theApp.m_model.m_hsmsPassive.requestAlarmReport(1, 2, "abc");
+ static int i = 0;
+ i++;
+ static char* pszText[] = {"123", "456", "789", "abc", "def"};
+ theApp.m_model.m_hsmsPassive.requestAlarmReport(i%3, i, pszText[i%5]);
}
diff --git a/SourceCode/Bond/Servo/HsmsAction.cpp b/SourceCode/Bond/Servo/HsmsAction.cpp
index 0792df5..1c0d71c 100644
--- a/SourceCode/Bond/Servo/HsmsAction.cpp
+++ b/SourceCode/Bond/Servo/HsmsAction.cpp
@@ -104,7 +104,7 @@
BOOL CHsmsAction::incrementAndCheckTimeout()
{
unsigned int nResponseTime = InterlockedIncrement(&m_nResponseTime);
- return nResponseTime >= m_nTimeout;
+ return nResponseTime >= m_nTimeout + 1;
}
int CHsmsAction::serialize(char* pszBuffer, int nBufferSize)
diff --git a/SourceCode/Bond/Servo/HsmsPassive.cpp b/SourceCode/Bond/Servo/HsmsPassive.cpp
index 902f236..d3534c3 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.cpp
+++ b/SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -48,6 +48,7 @@
m_listener.onCommand = nullptr;
m_listener.onEQConstantRequest = nullptr;
m_listener.onEQConstantSend = nullptr;
+ m_pActiveAction = nullptr;
InitializeCriticalSection(&m_criticalSection);
}
@@ -62,6 +63,10 @@
delete item;
}
m_listActionSent.clear();
+ for (auto item : m_listActionSpooling) {
+ delete item;
+ }
+ m_listActionSpooling.clear();
Unlock();
if (m_hCimWorkEvent != NULL) {
@@ -151,11 +156,24 @@
{
LOGI("onRecvMsg:%s", pMessage->toString());
Lock();
+ if (m_pActiveAction != nullptr &&
+ (m_pActiveAction->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes)) {
+ SetEvent(m_pActiveAction->getEvent());
+ LOGI("CHsmsPassive::褰撳墠绛夊緟鏈夊洖澶�");
+ TRACE("CHsmsPassive::褰撳墠绛夊緟鏈夊洖澶峔n");
+ Unlock();
+ return 0;
+ }
+ Unlock();
+
+
+ Lock();
CHsmsAction* pAction = nullptr;
for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end(); iter++) {
if ((*iter)->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes) {
LOGI("CHsmsPassive::鎵惧埌");
pAction = (*iter);
+ SetEvent(pAction->getEvent());
m_listActionSent.erase(iter);
break;
}
@@ -460,17 +478,17 @@
};
auto onRecvSysMessage = [&](void* pFrom, IMessage* pMessage) -> void {
LOGI("<HSMS>onRecvSysMessage:sessionId:%d, sType:%d systemBytes:%d",
- pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
onRecvMsg(pMessage);
if (MSG_LINKTEST_REQ == pMessage->getHeader()->sType) {
- /*
- Sleep(10);
- if (!m_bAreYouThereRequest) {
- m_bAreYouThereRequest = TRUE;
- requestYouThere();
- }
- */
+ /*
+ Sleep(10);
+ if (!m_bAreYouThereRequest) {
+ m_bAreYouThereRequest = TRUE;
+ requestYouThere();
}
+ */
+}
};
auto onError = [&](void* pFrom, int error) -> void {
@@ -527,6 +545,9 @@
else if (nStream == 5 && pHeader->function == 3) {
replyEanbleDisableAlarmReport(pMessage);
}
+ else if (nStream == 6 && pHeader->function == 23) {
+ replyPurgeSpooledData(pMessage);
+ }
else if (nStream == 7 && pHeader->function == 19) {
replyQueryPPIDList(pMessage);
}
@@ -554,6 +575,42 @@
return 0;
}
+int CHsmsPassive::loadCacheFromFile(const char* pszFilepath)
+{
+ m_strCacheFilepath = pszFilepath;
+
+ CFile file;
+ if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeRead) ) {
+ return -1;
+ }
+
+ int nBufSize = file.GetLength();
+ char* pszBuffer = new char[nBufSize];
+ file.Read(pszBuffer, nBufSize);
+ file.Close();
+ int nRet = unserialize(pszBuffer, nBufSize);
+ delete[] pszBuffer;
+
+ return nRet;
+}
+
+int CHsmsPassive::saveCache()
+{
+ CFile file;
+ if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeWrite | CFile::modeCreate)) {
+ return -1;
+ }
+
+ int nSize = serialize(nullptr, 0);
+ char* pszBuffer = new char[nSize];
+ int nRet = serialize(pszBuffer, nSize);
+ file.Write(pszBuffer, nSize);
+ file.Close();
+ delete[] pszBuffer;
+
+ return nRet;
+}
+
int CHsmsPassive::term()
{
// 缁撴潫绾跨▼
@@ -577,6 +634,53 @@
return 0;
}
+int CHsmsPassive::serialize(char* pszBuffer, int nBufferSize)
+{
+ int index = 0;
+ if (pszBuffer == nullptr) {
+ index += sizeof(int);
+ for (auto item : m_listActionSpooling) {
+ index += item->serialize(pszBuffer, nBufferSize);
+ }
+
+ return index;
+ }
+ else {
+ int nTemp, nRet;
+
+ nTemp = (int)m_listActionSpooling.size();
+ memcpy(&pszBuffer[index], &nTemp, sizeof(int));
+ index += sizeof(int);
+
+ for (auto item : m_listActionSpooling) {
+ nRet = item->serialize(&pszBuffer[index], nBufferSize);
+ if (nRet <= 0) break;
+ index += nRet;
+ }
+
+ return index;
+ }
+}
+
+int CHsmsPassive::unserialize(const char* pszBuffer, int nBufferSize)
+{
+ int index = 0, nTemp, nRet = 0;
+
+ if (index + sizeof(int) > nBufferSize) return -1;
+ memcpy(&nTemp, &pszBuffer[index], sizeof(int));
+ index += sizeof(int);
+
+ for (int i = 0; i < nTemp; i++) {
+ CHsmsAction* pAction = new CHsmsAction();
+ nRet = pAction->unserialize(&pszBuffer[index], nBufferSize - index);
+ if (nRet <= 0) break;
+ index += nRet;
+ m_listActionSpooling.push_back(pAction);
+ }
+
+ return index + nRet;
+}
+
unsigned CHsmsPassive::OnCimWork()
{
while (m_bCimWorking) {
@@ -595,17 +699,26 @@
while (!list.empty()) {
Lock();
CHsmsAction* pAction = list.front();
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ m_listActionSpooling.push_back(pAction);
+ Unlock();
+ continue;
+ }
Unlock();
list.pop_front();
TRACE("OnCimWork 004.\n");
- IMessage* pMessage = pAction->getSendMessage();
- ASSERT(pMessage);
- m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
-
if (pAction->isNeedWaitReply()) {
// 濡傛灉闇�瑕佺瓑寰呭洖澶�
+ Lock();
+ m_pActiveAction = pAction;
+ IMessage* pMessage = pAction->getSendMessage();
+ Unlock();
+
+ ASSERT(pMessage);
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+
int nRet = WaitForSingleObject(pAction->getEvent(), pAction->getTimeout() * 1000);
if (nRet == WAIT_TIMEOUT) {
TRACE("Timeout...\n");
@@ -616,18 +729,22 @@
//pContext->setEvent();
}
}
-
- delete pAction;
- pAction = NULL;
- TRACE("delete m_pCurrentAction, next...\n");
+ Lock();
+ delete m_pActiveAction;
+ m_pActiveAction = nullptr;
+ Unlock();
}
else {
Lock();
m_listActionSent.push_back(pAction);
+ IMessage* pMessage = pAction->getSendMessage();
Unlock();
+
+ ASSERT(pMessage);
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+
}
-
-
}
TRACE("OnCimWork \n");
@@ -732,6 +849,7 @@
return 0;
}
+// S1F13
int CHsmsPassive::replyEstablishCommunications(IMessage* pRecv)
{
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
@@ -1149,6 +1267,47 @@
return 0;
}
+// S6F23
+int CHsmsPassive::replyPurgeSpooledData(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::U1) ER_PARAM_ERROR;
+ unsigned char RSDC; // 0 - transmit; 1 - purge;
+ pBody->getU1(RSDC);
+ if (RSDC != 0 && RSDC != 1) ER_PARAM_ERROR;
+
+ BYTE ACK = 0; // 0 - ok; 1 - retryable busy; 2 - no spool data;
+ if (m_listActionSpooling.empty()) {
+ ACK = 2;
+ }
+ replyAck(6, 24, pRecv->getHeader()->systemBytes, ACK, "RSDA");
+
+
+ // 涓㈠純
+ if (RSDC == 1) {
+ Lock();
+ for (auto item : m_listActionSpooling) {
+ delete item;
+ }
+ m_listActionSpooling.clear();
+ Unlock();
+ }
+ else {
+ Lock();
+ for (auto item : m_listActionSpooling) {
+ m_listAction.push_back(item);
+ }
+ m_listActionSpooling.clear();
+ Unlock();
+ SetEvent(m_hCimWorkEvent);
+ }
+
+ return 0;
+}
+
// S7F19
int CHsmsPassive::replyQueryPPIDList(IMessage* pRecv)
{
@@ -1209,16 +1368,12 @@
// S5F1
int CHsmsPassive::requestAlarmReport(int ALCD, int ALID, const char* ALTX)
{
- if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- return ER_NOTSELECT;
- }
-
char szALCD[1];
szALCD[0] = ALCD & 0xff;
Lock();
CHsmsAction* pAction = new CHsmsAction(ACTION_ALARM_REPORT, TRUE, m_nActionTimeout);
- m_listAction.push_back(pAction);
+
IMessage* pMessage = NULL;
HSMS_Create1Message(pMessage, m_nSessionId, 5 | REPLY, 1, ++m_nSystemByte);
ASSERT(pMessage);
@@ -1227,21 +1382,14 @@
pItem->addU4Item(ALID, "ALID");
pItem->addItem(ALTX, "ALTX");
pAction->setSendMessage(pMessage);
-
- SetEvent(m_hCimWorkEvent);
- Unlock();
-
- int size = pAction->serialize(nullptr, 0);;
- if (size > 0) {
- char* pszBuffer = new char[size];
- pAction->serialize(pszBuffer, size);
- AfxMessageBox("abc");
-
- CHsmsAction* pAction2 = new CHsmsAction();
- pAction2->unserialize(pszBuffer, size);
- AfxMessageBox("def");
- m_pPassive->sendMessage(pAction2->getSendMessage());
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ m_listActionSpooling.push_back(pAction);
}
+ else {
+ m_listAction.push_back(pAction);
+ SetEvent(m_hCimWorkEvent);
+ }
+ Unlock();
return ER_NOERROR;
}
@@ -1249,10 +1397,6 @@
// S6F11
int CHsmsPassive::requestEventReportSend(unsigned int DATAID, unsigned int CEID, const std::vector<std::string>& values)
{
- if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- return ER_NOTSELECT;
- }
-
SERVO::CCollectionEvent* pEvent = getEvent(CEID);
if (pEvent == nullptr) {
return ER_NO_EVENT;
@@ -1263,7 +1407,6 @@
Lock();
CHsmsAction* pAction = new CHsmsAction(ACTION_EVENT_REPORT, TRUE, m_nActionTimeout);
- m_listAction.push_back(pAction);
IMessage* pMessage = NULL;
HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 11, ++m_nSystemByte);
ASSERT(pMessage);
@@ -1278,8 +1421,13 @@
pItemList3->addItem(item.c_str(), "V");
}
pAction->setSendMessage(pMessage);
-
- SetEvent(m_hCimWorkEvent);
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ m_listActionSpooling.push_back(pAction);
+ }
+ else {
+ m_listAction.push_back(pAction);
+ SetEvent(m_hCimWorkEvent);
+ }
Unlock();
return ER_NOERROR;
diff --git a/SourceCode/Bond/Servo/HsmsPassive.h b/SourceCode/Bond/Servo/HsmsPassive.h
index 84644a5..3fa3b73 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.h
+++ b/SourceCode/Bond/Servo/HsmsPassive.h
@@ -142,7 +142,11 @@
void OnTimer(UINT nTimerid);
void setActionTimeout(int nSecond);
int init(CModel* pModel, const char* pszName, unsigned int port);
+ int loadCacheFromFile(const char* pszFilepath);
+ int saveCache();
int term();
+ int serialize(char* pszBuffer, int nBufferSize);
+ int unserialize(const char* pszBuffer, int nBufferSize);
public:
/* request开头的函数为主动发送数据的函数 */
@@ -167,6 +171,7 @@
int replyCommand(IMessage* pRecv);
int replyConfigureSpooling(IMessage* pRecv);
int replyEanbleDisableAlarmReport(IMessage* pRecv);
+ int replyPurgeSpooledData(IMessage* pRecv);
int replyQueryPPIDList(IMessage* pRecv);
int replyTerminalDisplay(IMessage* pRecv);
@@ -189,6 +194,7 @@
CRITICAL_SECTION m_criticalSection;
std::list<CHsmsAction*> m_listAction;
std::list<CHsmsAction*> m_listActionSent;
+ std::list<CHsmsAction*> m_listActionSpooling;
private:
SECSListener m_listener;
@@ -196,6 +202,8 @@
HANDLE m_hCimWorkEvent;
HANDLE m_hCimWorkThreadHandle;
unsigned m_nCimWorkThrdaddr;
+ std::string m_strCacheFilepath;
+ CHsmsAction* m_pActiveAction;
private:
// CVariable vector
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 3427f45..ace0bd4 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -148,6 +148,8 @@
m_hsmsPassive.loadReports((LPTSTR)(LPCTSTR)strVarialbleFile);
strVarialbleFile.Format(_T("%s\\CollectionEventList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
m_hsmsPassive.loadCollectionEvents((LPTSTR)(LPCTSTR)strVarialbleFile);
+ strVarialbleFile.Format(_T("%s\\HsmsPassive.cache"), (LPTSTR)(LPCTSTR)m_strWorkDir);
+ m_hsmsPassive.loadCacheFromFile(strVarialbleFile);
SERVO::MasterListener masterListener;
@@ -337,6 +339,7 @@
int CModel::term()
{
+ m_hsmsPassive.saveCache();
m_hsmsPassive.term();
CLog::GetLog()->SetOnLogCallback(nullptr);
m_master.term();
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 04cab1e..552795b 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 457a1fe..84b1f21 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -189,6 +189,7 @@
SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
if (state == SERVO::MASTERSTATE::READY) {
m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
@@ -204,13 +205,15 @@
}
else if (state == SERVO::MASTERSTATE::MSERROR) {
m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM);
m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
m_pMyStatusbar->setRunTimeText("启动失败.");
}
- else if (state == SERVO::MASTERSTATE::RUNNING) {
+ else if (state == SERVO::MASTERSTATE::RUNNING || state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
m_pMyStatusbar->setForegroundColor(RGB(255, 255, 255));
@@ -937,6 +940,18 @@
else {
if (theApp.m_model.getMaster().start() == 0) {
m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
+ }
+ }
+ }
+ else if (id == IDC_BUTTON_RUN_CT) {
+ if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
+ AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
+ }
+ else {
+ if (theApp.m_model.getMaster().startContinuousTransfer() == 0) {
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+ m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
}
}
}
@@ -1057,6 +1072,9 @@
if (state == SERVO::MASTERSTATE::RUNNING) {
strText.Format(_T("正在运行:%02d:%02d:%02d %s"), h, m, s, pszSuffix);
}
+ else if (state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
+ strText.Format(_T("千传模式:%02d:%02d:%02d %s"), h, m, s, pszSuffix);
+ }
else {
strText.Format(_T("已运行:%02d:%02d:%02d %s"), h, m, s, pszSuffix);
}
diff --git a/SourceCode/Bond/Servo/TopToolbar.cpp b/SourceCode/Bond/Servo/TopToolbar.cpp
index a601129..0208ece 100644
--- a/SourceCode/Bond/Servo/TopToolbar.cpp
+++ b/SourceCode/Bond/Servo/TopToolbar.cpp
@@ -27,6 +27,7 @@
{
CDialogEx::DoDataExchange(pDX);
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_ALARM, m_btnAlarm);
DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
@@ -52,6 +53,7 @@
CDialogEx::OnInitDialog();
InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
+ 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_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
@@ -112,6 +114,11 @@
int x = 2, y = 3;
pItem = GetDlgItem(IDC_BUTTON_RUN);
+ pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+ x += BTN_WIDTH;
+ x += 2;
+
+ pItem = GetDlgItem(IDC_BUTTON_RUN_CT);
pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
x += BTN_WIDTH;
x += 2;
@@ -190,6 +197,7 @@
{
switch (LOWORD(wParam)) {
case IDC_BUTTON_RUN:
+ case IDC_BUTTON_RUN_CT:
case IDC_BUTTON_STOP:
case IDC_BUTTON_ALARM:
case IDC_BUTTON_SETTINGS:
diff --git a/SourceCode/Bond/Servo/TopToolbar.h b/SourceCode/Bond/Servo/TopToolbar.h
index e4e0408..6400443 100644
--- a/SourceCode/Bond/Servo/TopToolbar.h
+++ b/SourceCode/Bond/Servo/TopToolbar.h
@@ -31,6 +31,7 @@
private:
CBlButton m_btnRun;
+ CBlButton m_btnRunCt;
CBlButton m_btnStop;
CBlButton m_btnAlarm;
CBlButton m_btnSettings;
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index 3a430cc..3658421 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico b/SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico
new file mode 100644
index 0000000..bb7d956
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico b/SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico
new file mode 100644
index 0000000..ef3c3f9
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico
Binary files differ
--
Gitblit v1.9.3