| | |
| | | #include "Model.h" |
| | | #include "Log.h" |
| | | #include "ToolUnits.h" |
| | | #include "Alarm.h" |
| | | #include "EQState.h" |
| | | |
| | | |
| | | CModel* g_pModel = NULL; |
| | |
| | | { |
| | | m_pObservableEmitter = nullptr; |
| | | m_pObservable = nullptr; |
| | | m_pServo = nullptr; |
| | | m_pEqBond1 = nullptr; |
| | | m_pEquipment = nullptr; |
| | | m_nTimerID = 0; |
| | | } |
| | | |
| | |
| | | void CModel::setWorkDir(const char* pszWorkDir) |
| | | { |
| | | m_strWorkDir = pszWorkDir; |
| | | m_bonder.setWorkDir(pszWorkDir); |
| | | } |
| | | |
| | | int CModel::init() |
| | |
| | | |
| | | |
| | | // 创建Servo |
| | | BEQ_CreateServo(m_pServo, "BLServo"); |
| | | ASSERT(m_pServo); |
| | | BEQ::ServoListener listener; |
| | | listener.onRemoteEqConnecting = [&](void* pServo, void* pRemoteEiuipment) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGI("<ServoListener>正在连接远程设备(%s)...", szBuffer); |
| | | BEQ_CreateEquipment(m_pEquipment, "BLBonder"); |
| | | ASSERT(m_pEquipment); |
| | | BEQ::EquipmentListener listener; |
| | | listener.onConnected = [&](void* pEiuipment, const char* pszAddr, int port) -> void { |
| | | LOGI("<EquipmentListener>连接进入(%s:%d).", pszAddr, port); |
| | | notifyPtr(RX_CODE_EQ_STATE_CHANGED, pEiuipment); |
| | | }; |
| | | listener.onRemoteEqConnected = [&](void* pServo, void* pRemoteEiuipment) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGI("<ServoListener>连接远程设备(%s)成功.", szBuffer); |
| | | notifyPtr(RX_CODE_REMOTEEQ_STATE_CHANGED, pRemoteEiuipment); |
| | | listener.onDisconnected = [&](void* pEiuipment, const char* pszAddr, int port) -> void { |
| | | LOGI("<EquipmentListener>连接断开(%s:%d).", pszAddr, port); |
| | | notifyPtr(RX_CODE_EQ_STATE_CHANGED, pEiuipment); |
| | | }; |
| | | listener.onRemoteEqConnectFailed = [&](void* pServo, void* pRemoteEiuipment, int errorCode) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGW("<ServoListener>连接远程设备(%s)失败.", szBuffer); |
| | | }; |
| | | listener.onRemoteEqDisconnecting = [&](void* pServo, void* pRemoteEiuipment) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGI("<ServoListener>正在断开远程设备(%s).", szBuffer); |
| | | }; |
| | | listener.onRemoteEqDisconnected = [&](void* pServo, void* pRemoteEiuipment) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGW("<ServoListener>远程设备(%s)连接断开.", szBuffer); |
| | | notifyPtr(RX_CODE_REMOTEEQ_STATE_CHANGED, pRemoteEiuipment); |
| | | }; |
| | | listener.onRemoteEqReadRawdata = [&](void* pServo, void* pRemoteEiuipment, const char* pszData, int len) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGD("<ServoListener>收到远程设备(%s)原始数据(%s).", szBuffer, std::string(pszData, len).c_str()); |
| | | }; |
| | | listener.onRemoteEqEventUpdate = [&](void* pServo, void* pRemoteEiuipment, void* pUnit, BEQ::REMOTE_EQ_EVENT eventCode) -> void { |
| | | BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment; |
| | | char szBuffer[256]; |
| | | p->getName(szBuffer, 256); |
| | | LOGD("<ServoListener>远程设备(%s)onRemoteEqEventUpdate.", szBuffer); |
| | | }; |
| | | m_pServo->setListener(listener); |
| | | // 注意此处还有几个回调函数未处理 |
| | | m_pEquipment->setEquipmentListener(listener); |
| | | |
| | | |
| | | m_pObservable = RX_AllocaObservable([&](IObservableEmitter* e) -> void { |
| | |
| | | g_pModel = this; |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | BondListener bonderListener; |
| | | bonderListener.onStateChanged = [&](void* pFrom, int state) -> void { |
| | | notifyInt(RX_CODE_BONDER_STATE_CHANGED, state); |
| | | }; |
| | | bonderListener.onPlcStateChanged = [&](void* pFrom, int state) -> void { |
| | | PLCSTATE ps = (PLCSTATE)state; |
| | | if (ps == PLCSTATE::CONNECTED) { |
| | | notifyPtrAndInt(RX_CODE_PLC1_CONNECTTD, pFrom, 0, state); |
| | | } |
| | | else if (ps == PLCSTATE::DISCONNECTED) { |
| | | notifyPtrAndInt(RX_CODE_PLC1_DISCONNECTTD, pFrom, 0, state); |
| | | } |
| | | }; |
| | | bonderListener.onEfemStateChanged = [&](void* pFrom, const char* pszAddr, int port, int state) -> void { |
| | | if (m_pObservableEmitter != NULL) { |
| | | IAny* pAny = RX_AllocaAny(); |
| | | if (pAny != NULL) { |
| | | pAny->addRef(); |
| | | pAny->setCode(RX_CODE_EFEM_STATUS_CHANGED); |
| | | pAny->setStringValue("addr", pszAddr); |
| | | pAny->setIntValue("port", port); |
| | | pAny->setIntValue("state", state); |
| | | m_pObservableEmitter->onNext(pAny); |
| | | pAny->release(); |
| | | } |
| | | } |
| | | }; |
| | | bonderListener.onRecvBroadcast = [&](void* pFrom, void* p) -> void { |
| | | CComponent* pSender = (CComponent*)pFrom; |
| | | CIntent* pIntent = (CIntent*)p; |
| | | int code = pIntent->getCode(); |
| | | if (code == BC_CODE_DATA1_MATERIAL_RECEIVED) { |
| | | notifyPtr(RX_CODE_DATA1_MATERIAL_RECEIVED, pSender); |
| | | } |
| | | else if (code == BC_CODE_DATA1_BEGIN_SAMPLING) { |
| | | notifyPtr(RX_CODE_DATA1_BEGIN_SAMPLING, pSender); |
| | | } |
| | | else if (code == BC_CODE_DATA1_UPDATE) { |
| | | notifyPtr(RX_CODE_DATA1_UPDATE, pSender); |
| | | } |
| | | else if (code == BC_CODE_DATA1_END_SAMPLING) { |
| | | notifyPtr(RX_CODE_DATA1_END_SAMPLING, pSender); |
| | | } |
| | | else if (code == BC_CODE_DATA1_MATERIAL_REMOVED) { |
| | | std::string strError; |
| | | CPanel* pPanel = (CPanel*)pIntent->getContext(); |
| | | pPanel->addRef(); |
| | | savePanel(pPanel, pSender); |
| | | m_sqlite.insertPanel(pPanel, strError); |
| | | notifyPtr(RX_CODE_DATA1_MATERIAL_REMOVEED, pSender); |
| | | notifyObj(RX_CODE_PANEL_COMPLATE, pPanel); |
| | | pPanel->release(); |
| | | } |
| | | else if (code == BC_CODE_ALARM_ON) { |
| | | CAlarm* pAlarm = (CAlarm*)pIntent->getContext(); |
| | | pAlarm->addRef(); |
| | | notifyObjAndPtr(RX_CODE_ALARM_ON, pAlarm, pSender); |
| | | pAlarm->release(); |
| | | } |
| | | else if (code == BC_CODE_ALARM_OFF) { |
| | | CAlarm* pAlarm = (CAlarm*)pIntent->getContext(); |
| | | pAlarm->addRef(); |
| | | notifyObjAndPtr(RX_CODE_ALARM_OFF, pAlarm, pSender); |
| | | pAlarm->release(); |
| | | } |
| | | else if (code == BC_CODE_EQSTATE_EVENT) { |
| | | CEQState* pState = (CEQState*)pIntent->getContext(); |
| | | pState->addRef(); |
| | | notifyObjAndPtr(RX_CODE_EQSTATE_EVENT, pState, pSender); |
| | | pState->release(); |
| | | } |
| | | }; |
| | | m_bonder.setListener(bonderListener); |
| | | m_bonder.init(); |
| | | |
| | | int CModel::createRemoteEqs() |
| | | { |
| | | // 从配置中读取远程机器配置 |
| | | CString strIp, strIniFile; |
| | | UINT nPort, nDoorCount; |
| | | strIniFile.Format(_T("%s\\Configuration.ini"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | CConfiguration configuration((LPTSTR)(LPCTSTR)strIniFile); |
| | | configuration.getBond1(strIp, nPort, nDoorCount); |
| | | m_pServo->createRemoteEquipment(m_pEqBond1, (LPTSTR)(LPCTSTR)strIp, nPort); |
| | | ASSERT(m_pEqBond1); |
| | | m_pEqBond1->addUnit("UNITA", nDoorCount); |
| | | m_pServo->connectRemoteEquipment(m_pEqBond1); |
| | | |
| | | CString strBonderDataFile; |
| | | strBonderDataFile.Format(_T("%s\\Bonder.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | m_bonder.read((LPTSTR)(LPCTSTR)strBonderDataFile); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CModel::term() |
| | | { |
| | | m_bonder.save(); |
| | | m_bonder.term(); |
| | | m_sqlite.term(); |
| | | |
| | | CLog::GetLog()->SetOnLogCallback(nullptr); |
| | | return 0; |
| | | } |
| | |
| | | return m_bonder; |
| | | } |
| | | |
| | | BEQ::IRemoteEquipment* CModel::getBond1() |
| | | BEQ::IEquipment* CModel::getEquipment() |
| | | { |
| | | return m_pEqBond1; |
| | | return m_pEquipment; |
| | | } |
| | | |
| | | int CModel::notify(int code) |
| | |
| | | |
| | | void CModel::onTimer(UINT nTimerid) |
| | | { |
| | | ULONGLONG tick = GetTickCount64(); |
| | | int interval = m_configuration.getP2RemoteEqReconnectInterval() * 1000; |
| | | |
| | | if (m_pEqBond1 != nullptr) { |
| | | if (!m_pEqBond1->isConnected()) { |
| | | if (tick - m_pEqBond1->getConnectTick() > interval) { |
| | | m_pEqBond1->connect(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | int CModel::savePanel(CPanel* pPanel, CComponent* pComponent) |
| | | { |
| | | int year, month, day; |
| | | pPanel->getReceivedTime(year, month, day); |
| | | CString strDir, strFilepath; |
| | | strDir.Format("%s\\%d\\%d\\%d", (LPTSTR)(LPCTSTR)m_strDataDir, year, month, day); |
| | | CToolUnits::createDir((LPTSTR)(LPCTSTR)strDir); |
| | | strFilepath.Format("%s\\%s.csv", (LPTSTR)(LPCTSTR)strDir, pPanel->getQRCode().c_str()); |
| | | |
| | | CStdioFile file; |
| | | if (!file.Open(strFilepath, CFile::modeCreate | CFile::modeWrite)) { |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | // 基本信息 |
| | | // 来源, id,开始采样时间,结束采样时间 |
| | | CString strLine; |
| | | file.WriteString("# 统计\n"); |
| | | strLine.Format(_T("来源,%s\n"), pComponent->getName().c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("id,%s\n"), pPanel->getQRCode().c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("来料时间,%s\n"), |
| | | CToolUnits::timeToString3(pPanel->getReceivedTime()).c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("采样开始时间,%s\n"), |
| | | CToolUnits::timeToString3(pPanel->getBeginSamplingTime()).c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("采样结束时间,%s\n"), |
| | | CToolUnits::timeToString3(pPanel->getEndSamplingTime()).c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("出料时间,%s\n"), |
| | | CToolUnits::timeToString3(pPanel->getRemovedTime()).c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("Recipe name,%s\n"), pPanel->getRecipeName().c_str()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("干泵吸真空值,%f\n"), pPanel->getAir1()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("分子泵吸真空值,%f\n"), pPanel->getAir2()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("气囊压力值,%f\n"), pPanel->getAir3()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("贴合总压力,%d\n"), pPanel->getPre1()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("上腔体温度,%f\n"), pPanel->getTmp1()); |
| | | file.WriteString(strLine); |
| | | strLine.Format(_T("下腔体温度,%f\n"), pPanel->getTmp2()); |
| | | file.WriteString(strLine); |
| | | file.WriteString("\n"); |
| | | |
| | | |
| | | // 统计区 |
| | | file.WriteString("# 统计\n"); |
| | | file.WriteString("项,上腔体温度(℃),下腔体温度(℃),上腔体温度1(℃),上腔体温度2(℃),上腔体温度3(℃),上腔体温度4(℃),上腔体温度5(℃),下腔体温度1(℃),下腔体温度2(℃),下腔体温度3(℃),下腔体温度4(℃),下腔体温度5(℃),腔体真空(Pa),腔体压力1(Kg),腔体压力2(Kg),腔体压力3(Kg),腔体压力4(Kg),腔体压力5(Kg)\n"); |
| | | UNITDATA1 dataMax = pPanel->getMathData(IMAX); |
| | | strLine.Format(_T("最大值,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.03f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f\n"), |
| | | dataMax.temp[0], dataMax.temp[1], |
| | | dataMax.temp[2], dataMax.temp[3], dataMax.temp[4], dataMax.temp[5], dataMax.temp[6], |
| | | dataMax.temp[7], dataMax.temp[8], dataMax.temp[9], dataMax.temp[10], dataMax.temp[11], |
| | | dataMax.vacuum, |
| | | dataMax.pressure[0], dataMax.pressure[1], dataMax.pressure[2], |
| | | dataMax.pressure[3], dataMax.pressure[4]); |
| | | file.WriteString(strLine); |
| | | |
| | | UNITDATA1 dataMin = pPanel->getMathData(IMIN); |
| | | strLine.Format(_T("最小值,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.03f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f\n"), |
| | | dataMin.temp[0], dataMin.temp[1], |
| | | dataMin.temp[2], dataMin.temp[3], dataMin.temp[4], dataMin.temp[5], dataMin.temp[6], |
| | | dataMin.temp[7], dataMin.temp[8], dataMin.temp[9], dataMin.temp[10], dataMin.temp[11], |
| | | dataMin.vacuum, |
| | | dataMin.pressure[0], dataMin.pressure[1], dataMin.pressure[2], |
| | | dataMin.pressure[3], dataMin.pressure[4]); |
| | | file.WriteString(strLine); |
| | | |
| | | UNITDATA1 dataAve = pPanel->getMathData(IAVE); |
| | | strLine.Format(_T("平均值,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.03f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f\n"), |
| | | dataAve.temp[0], dataAve.temp[1], |
| | | dataAve.temp[2], dataAve.temp[3], dataAve.temp[4], dataAve.temp[5], dataAve.temp[6], |
| | | dataAve.temp[7], dataAve.temp[8], dataAve.temp[9], dataAve.temp[10], dataAve.temp[11], |
| | | dataAve.vacuum, |
| | | dataAve.pressure[0], dataAve.pressure[1], dataAve.pressure[2], |
| | | dataAve.pressure[3], dataAve.pressure[4]); |
| | | file.WriteString(strLine); |
| | | file.WriteString("\n"); |
| | | |
| | | |
| | | // 数据区 |
| | | file.WriteString("# 数据区\n"); |
| | | file.WriteString("时间,上腔体温度(℃),下腔体温度(℃),上腔体温度1(℃),上腔体温度2(℃),上腔体温度3(℃),上腔体温度4(℃),上腔体温度5(℃),下腔体温度1(℃),下腔体温度2(℃),下腔体温度3(℃),下腔体温度4(℃),下腔体温度5(℃),腔体真空(Pa),腔体压力1(Kg),腔体压力2(Kg),腔体压力3(Kg),腔体压力4(Kg),腔体压力5(Kg)\n"); |
| | | std::vector<UNITDATA1> datas; |
| | | pPanel->getDatas(datas); |
| | | for (auto item : datas) { |
| | | strLine.Format(_T("%s,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.03f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f,%.01f\n"), |
| | | CToolUnits::timeToString3(item.time).c_str(), |
| | | item.temp[0], item.temp[1], |
| | | item.temp[2], item.temp[3], item.temp[4], item.temp[5], item.temp[6], |
| | | item.temp[7], item.temp[8], item.temp[9], item.temp[10], item.temp[11], |
| | | item.vacuum, |
| | | item.pressure[0], item.pressure[1], item.pressure[2], |
| | | item.pressure[3], item.pressure[4]); |
| | | file.WriteString(strLine); |
| | | } |
| | | |
| | | |
| | | file.Close(); |
| | | |
| | | return 0; |
| | | } |