#include "stdafx.h" #include "CGlass.h" #include "Log.h" namespace SERVO { CGlass::CGlass() { m_pPath = nullptr; m_type = MaterialsType::G1; m_pBuddy = nullptr; m_nOriginPort = 0; m_nOriginSlot = 0; m_bScheduledForProcessing = FALSE; m_pProcessJob = nullptr; } CGlass::~CGlass() { reset(); } void CGlass::reset() { CPath* pPath = m_pPath; while (pPath != nullptr) { CPath* pTemp = pPath->getNext(); delete pPath; pPath = pTemp; } m_pPath = nullptr; if (m_pBuddy != nullptr) { m_pBuddy->release(); m_pBuddy = nullptr; } } std::string& CGlass::getClassName() { static std::string strName = "CGlass"; return strName; } std::string CGlass::toString() { std::string strText; strText += "CGlass["; strText += ("ID:" + m_strID + ";"); strText += "]"; return strText; } MaterialsType CGlass::getType() const { return m_type; } void CGlass::setType(MaterialsType type) { m_type = type; } void CGlass::setID(const char* pszID) { m_strID = pszID; } const std::string& CGlass::getID() const { return m_strID; } void CGlass::setOriginPort(int port, int slot) { m_nOriginPort = port; m_nOriginSlot = slot; } void CGlass::getOrginPort(int& port, int& slot) { port = m_nOriginPort; slot = m_nOriginSlot; } BOOL CGlass::isScheduledForProcessing() { return m_bScheduledForProcessing; } 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 m_pPath; } std::string CGlass::getPathDescription() const { std::string strOut, strPath; char szBuffer[256]; CPath* pTemp = m_pPath; while (pTemp != nullptr) { pTemp->getSimpleDescription(strPath); if (strPath.compare("ARM1") != 0 && strPath.compare("ARM2") != 0) { if (!strOut.empty()) strOut.append(" -> "); strOut.append(strPath); } pTemp = pTemp->getNext(); } return strOut; } CPath* CGlass::getPathWithEq(unsigned int nEqId, unsigned int nUnit) const { CPath* pTemp = m_pPath; while (pTemp != nullptr) { if (pTemp->getEqID() == nEqId && pTemp->getUnit() == nUnit) { return pTemp; } pTemp = pTemp->getNext(); } return nullptr; } void CGlass::addPath(unsigned int nEqId, unsigned int nUnit, unsigned int slot) { CPath* pPath = new CPath(nEqId, nUnit, slot); if (m_pPath == nullptr) { m_pPath = pPath; } else { m_pPath->addPath(pPath); } } void CGlass::serialize(CArchive& ar) { if (ar.IsStoring()) { Lock(); ar << (int)m_type; WriteString(ar, m_strID); ar << m_nOriginPort; ar << m_nOriginSlot; ar << m_bScheduledForProcessing; ar << (ULONGLONG)m_pPath; if (m_pPath != nullptr) { m_pPath->serialize(ar); } char temp[JOBDATAS_SIZE] = { 0 }; m_jobDataS.serialize(temp, JOBDATAS_SIZE); ar.Write(temp, JOBDATAS_SIZE); ar << (ULONGLONG)m_pBuddy; WriteString(ar, m_strBuddyId); Unlock(); } else { ULONGLONG ullPath; int type; Lock(); ar >> type; m_type = (MaterialsType)type; ReadString(ar, m_strID); ar >> m_nOriginPort; ar >> m_nOriginSlot; ar >> m_bScheduledForProcessing; ar >> ullPath; if (ullPath != 0) { m_pPath = new CPath(); m_pPath->serialize(ar); } char temp[JOBDATAS_SIZE]; ar.Read(temp, JOBDATAS_SIZE); m_jobDataS.unserialize(temp, JOBDATAS_SIZE); ar >> ullPath; m_pBuddy = (CGlass*)ullPath; ReadString(ar, m_strBuddyId); Unlock(); } } void CGlass::setJobDataS(CJobDataS* pJobDataS) { m_jobDataS.copy(pJobDataS); } void CGlass::updateJobDataS(CJobDataS* pJobDataS) { m_jobDataS.update(pJobDataS); } CJobDataS* CGlass::getJobDataS() { return &m_jobDataS; } BOOL CGlass::setBuddy(CGlass* pGlass) { if (m_pBuddy != nullptr) return FALSE; if (pGlass->getType() == this->getType()) return FALSE; m_pBuddy = pGlass; m_pBuddy->addRef(); m_strBuddyId = m_pBuddy->getID(); return TRUE; } BOOL CGlass::forceSetBuddy(CGlass* pGlass) { m_pBuddy = pGlass; m_pBuddy->addRef(); m_strBuddyId = m_pBuddy->getID(); return TRUE; } CGlass* CGlass::getBuddy() { return m_pBuddy; } const std::string& CGlass::getBuddyId() const { return m_strBuddyId; } void CGlass::setBuddyId(std::string& strId) { m_strBuddyId = strId; } int CGlass::processEnd(unsigned int nEqId, unsigned int nUnit) { CPath* pPath = getPathWithEq(nEqId, nUnit); if (pPath == nullptr) return -1; pPath->processEnd(); return 0; } BOOL CGlass::isProcessed(unsigned int nEqId, unsigned int nUnit) { CPath* pPath = getPathWithEq(nEqId, nUnit); if (pPath == nullptr) return FALSE; return pPath->isProcessEnd(); } int CGlass::setInspResult(unsigned int nEqId, unsigned int nUnit, InspResult result) { CPath* pPath = getPathWithEq(nEqId, nUnit); if (pPath == nullptr) return -1; pPath->setInspResult(result); return 0; } InspResult CGlass::getInspResult(unsigned int nEqId, unsigned int nUnit) const { CPath* pPath = getPathWithEq(nEqId, nUnit); if (pPath == nullptr) return InspResult::NotInspected; return pPath->getInspResult(); } InspResult CGlass::getAOIInspResult() const { return getInspResult(EQ_ID_MEASUREMENT, 0); } 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 "Completed"; 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_state = GlsState::InProcess; m_tStart = std::chrono::system_clock::now(); } void CGlass::markEnd() { m_state = GlsState::Completed; m_tEnd = std::chrono::system_clock::now(); } void CGlass::addParams(std::vector& params) { m_params.insert(m_params.end(), params.begin(), params.end()); } std::vector& CGlass::getParams() { return m_params; } std::string CGlass::getParamsDescription() const { std::string strOut; char szBuffer[256]; for (auto p : m_params) { if (!strOut.empty()) strOut.append(","); if (p.getValueType() == PVT_INT) { sprintf_s(szBuffer, 256, "%s:%d", p.getName().c_str(), p.getIntValue()); } else if (p.getValueType() == PVT_DOUBLE) { sprintf_s(szBuffer, 256, "%s:%f", p.getName().c_str(), p.getDoubleValue()); } strOut.append(szBuffer); } return strOut; } // ========== SV数据口袋 ========== static constexpr size_t MAX_SV_DATA_KEEP = 4800; void CGlass::addSVData(int machineId, const std::string& dataType, const SVDataItem& dataItem) { auto& vec = m_svDatas[machineId][dataType]; vec.push_back(dataItem); if (vec.size() > MAX_SV_DATA_KEEP) { vec.erase(vec.begin(), vec.begin() + (vec.size() - MAX_SV_DATA_KEEP)); } } void CGlass::addSVData(int machineId, const std::string& dataType, double value) { auto now = std::chrono::system_clock::now(); auto& vec = m_svDatas[machineId][dataType]; vec.emplace_back(now, value); if (vec.size() > MAX_SV_DATA_KEEP) { vec.erase(vec.begin(), vec.begin() + (vec.size() - MAX_SV_DATA_KEEP)); } } void CGlass::addSVData(int machineId, const std::string& dataType, int64_t timestamp, double value) { // int64_t时间转成system_clock::time_point std::chrono::system_clock::time_point timePoint{ std::chrono::milliseconds(timestamp) // timestamp精度:毫秒 // 如果需要精度更高,可能要使用其他时间单位,如std::chrono::seconds(timestamp) }; auto& vec = m_svDatas[machineId][dataType]; vec.emplace_back(timePoint, value); if (vec.size() > MAX_SV_DATA_KEEP) { vec.erase(vec.begin(), vec.begin() + (vec.size() - MAX_SV_DATA_KEEP)); } } void CGlass::addSVData(int machineId, const std::string& dataType, const std::vector& dataItems) { auto& dataList = m_svDatas[machineId][dataType]; dataList.insert(dataList.end(), dataItems.begin(), dataItems.end()); if (dataList.size() > MAX_SV_DATA_KEEP) { dataList.erase(dataList.begin(), dataList.begin() + (dataList.size() - MAX_SV_DATA_KEEP)); } } std::vector CGlass::getSVData(int machineId, const std::string& dataType) const { auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { auto dataIt = machineIt->second.find(dataType); if (dataIt != machineIt->second.end()) { return dataIt->second; } } return std::vector(); } std::vector CGlass::getSVDataTypes(int machineId) const { std::vector types; auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { for (const auto& pair : machineIt->second) { types.push_back(pair.first); } } return types; } std::unordered_map> CGlass::getMachineSVData(int machineId) const { auto it = m_svDatas.find(machineId); if (it != m_svDatas.end()) { return it->second; } return std::unordered_map>(); } const std::unordered_map>>& CGlass::getAllSVData() const { return m_svDatas; } bool CGlass::hasSVData(int machineId, const std::string& dataType) const { auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { return machineIt->second.find(dataType) != machineIt->second.end(); } return false; } bool CGlass::hasMachineSVData(int machineId) const { return m_svDatas.find(machineId) != m_svDatas.end(); } std::vector CGlass::getMachineIdsWithSVData() const { std::vector machineIds; for (const auto& pair : m_svDatas) { machineIds.push_back(pair.first); } return machineIds; } void CGlass::clearSVData(int machineId, const std::string& dataType) { auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { machineIt->second.erase(dataType); if (machineIt->second.empty()) { m_svDatas.erase(machineIt); } } } void CGlass::clearMachineSVData(int machineId) { m_svDatas.erase(machineId); } void CGlass::clearAllSVData() { m_svDatas.clear(); } size_t CGlass::getSVDataCount(int machineId, const std::string& dataType) const { auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { auto dataIt = machineIt->second.find(dataType); if (dataIt != machineIt->second.end()) { return dataIt->second.size(); } } return 0; } size_t CGlass::getMachineSVDataCount(int machineId) const { size_t total = 0; auto machineIt = m_svDatas.find(machineId); if (machineIt != m_svDatas.end()) { for (const auto& pair : machineIt->second) { total += pair.second.size(); } } return total; } size_t CGlass::getTotalSVDataCount() const { size_t total = 0; for (const auto& machinePair : m_svDatas) { for (const auto& dataPair : machinePair.second) { total += dataPair.second.size(); } } return total; } std::vector> CGlass::findSVDataByType(const std::string& dataType) const { std::vector> result; for (const auto& machinePair : m_svDatas) { auto dataIt = machinePair.second.find(dataType); if (dataIt != machinePair.second.end()) { for (const auto& item : dataIt->second) { result.emplace_back(machinePair.first, item); } } } return result; } }