| | |
| | | #include "stdafx.h" |
| | | #include "stdafx.h" |
| | | #include "HsmsPassive.h" |
| | | #include "Log.h" |
| | | #include "Model.h" |
| | |
| | | { |
| | | for (auto it = m_mapReportIdToCEID.begin(); it != m_mapReportIdToCEID.end(); ) { |
| | | if (it->second == CEID) { |
| | | m_mapReportIdToCEID.erase(it++); // 更新迭代器 |
| | | m_mapReportIdToCEID.erase(it++); // 更新迭代器 |
| | | } |
| | | else { |
| | | ++it; |
| | |
| | | { |
| | | for (auto it = m_mapValueIdToPRTID.begin(); it != m_mapValueIdToPRTID.end(); ) { |
| | | if (it->second == RPTID) { |
| | | m_mapValueIdToPRTID.erase(it++); // 更新迭代器 |
| | | m_mapValueIdToPRTID.erase(it++); // 更新迭代器 |
| | | } |
| | | else { |
| | | ++it; |
| | |
| | | |
| | | void CHsmsPassive::OnTimer(UINT nTimerid) |
| | | { |
| | | // 所有已发送的Action自加1 |
| | | // 所有已发送的Action自加1 |
| | | Lock(); |
| | | for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end();) { |
| | | if ((*iter)->incrementAndCheckTimeout()) { |
| | | TRACE("CHsmsPassive::超时\n"); |
| | | TRACE("CHsmsPassive::超时\n"); |
| | | delete (*iter); |
| | | m_listActionSent.erase(iter++); |
| | | } |
| | |
| | | CHsmsAction* pAction = nullptr; |
| | | for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end(); iter++) { |
| | | if ((*iter)->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes) { |
| | | LOGI("CHsmsPassive::找到"); |
| | | LOGI("CHsmsPassive::找到"); |
| | | pAction = (*iter); |
| | | m_listActionSent.erase(iter); |
| | | break; |
| | |
| | | Unlock(); |
| | | |
| | | if (pAction != nullptr) { |
| | | LOGI("onRecvMsg::相应处理"); |
| | | LOGI("onRecvMsg::相应处理"); |
| | | delete pAction; |
| | | } |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CHsmsPassive::loadVarialbleList(const char* pszFilepath) |
| | | int CHsmsPassive::loadVarialbles(const char* pszFilepath) |
| | | { |
| | | CStdioFile file; |
| | | if (!file.Open(pszFilepath, CFile::modeRead)) { |
| | | return -1; |
| | | } |
| | | |
| | | std::regex pattern("^\\d+,.*"); // 匹配以数字+逗号开头的字符串 |
| | | std::regex pattern("^\\d+,.*"); // 匹配以数字+逗号开头的字符串 |
| | | std::vector<SERVO::CVariable*> variables; |
| | | int index, last; |
| | | CString strLine; |
| | |
| | | if (index < 0) continue; |
| | | strFormat = strLine.Mid(last, index - last); |
| | | strRemark = strLine.Right(strLine.GetLength() - index - 1); |
| | | strRemark.Replace(_T("\\r\\n"), _T("\r\n")); |
| | | |
| | | SERVO::CVariable* pVarialble = new SERVO::CVariable( |
| | | (LPTSTR)(LPCTSTR)strId, (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strFormat, (LPTSTR)(LPCTSTR)strRemark); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | std::vector<SERVO::CVariable*>& CHsmsPassive::getVariables() |
| | | { |
| | | return m_variabels; |
| | | } |
| | | |
| | | SERVO::CVariable* CHsmsPassive::getVariable(int variableId) |
| | | { |
| | | for (auto item : m_variabels) { |
| | | if (item->getVarialbleId() == variableId) { |
| | | return item; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | void CHsmsPassive::clearAllVariabel() |
| | | { |
| | | for (auto item : m_variabels) { |
| | | delete item; |
| | | } |
| | | m_variabels.clear(); |
| | | } |
| | | |
| | | int CHsmsPassive::loadReports(const char* pszFilepath) |
| | | { |
| | | CStdioFile file; |
| | | if (!file.Open(pszFilepath, CFile::modeRead)) { |
| | | return -1; |
| | | } |
| | | |
| | | std::regex pattern("^\\d+,\\(\\d+(,\\d+)*\\).*"); // 匹配以数字+逗号开头的字符串 |
| | | std::vector<SERVO::CReport*> reports; |
| | | int index; |
| | | CString strLine, strVariable; |
| | | CString strId, strName, strFormat, strRemark; |
| | | while (file.ReadString(strLine)) { |
| | | if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) { |
| | | continue; |
| | | } |
| | | |
| | | index = strLine.Find(",", 0); |
| | | if (index < 0) continue; |
| | | strId = strLine.Left(index); |
| | | strVariable = strLine.Right(strLine.GetLength() - index - 1); |
| | | strVariable.Delete(0); |
| | | strVariable.Delete(strVariable.GetLength() - 1); |
| | | auto vids = parseVidList(strVariable); |
| | | |
| | | |
| | | SERVO::CReport* pReport = new SERVO::CReport(atoi((LPTSTR)(LPCTSTR)strId)); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable(vid); |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | } |
| | | } |
| | | |
| | | reports.push_back(pReport); |
| | | } |
| | | |
| | | if (!reports.empty()) { |
| | | clearAllReport(); |
| | | for (auto item : reports) { |
| | | m_reports.push_back(item); |
| | | } |
| | | } |
| | | |
| | | |
| | | file.Close(); |
| | | return 0; |
| | | } |
| | | |
| | | std::vector<SERVO::CReport*>& CHsmsPassive::getReports() |
| | | { |
| | | return m_reports; |
| | | } |
| | | |
| | | void CHsmsPassive::clearAllReport() |
| | | { |
| | | for (auto item : m_reports) { |
| | | delete item; |
| | | } |
| | | m_reports.clear(); |
| | | } |
| | | |
| | | std::vector<int> CHsmsPassive::parseVidList(CString& strNums) |
| | | { |
| | | // 1. 先去掉可能出现的空白符(空格、制表符等) |
| | | strNums.Trim(); |
| | | |
| | | // 2️. |
| | | std::vector<int> result; |
| | | int i = 0; |
| | | CString strVid; |
| | | while (1) { |
| | | if (!AfxExtractSubString(strVid, (LPCTSTR)strNums, i, ',')) { |
| | | break; |
| | | } |
| | | if (!strVid.IsEmpty()) // 防御性检查 |
| | | result.push_back(std::stoi((LPTSTR)(LPCTSTR)strVid)); |
| | | i++; |
| | | |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | int CHsmsPassive::init(CModel* pModel, const char* pszName, unsigned int port) |
| | |
| | | auto onStatusChanged = [&](void* pFrom, STATE state) -> void { |
| | | m_pModel->notifyInt(RX_CODE_PASSIVE_STATUS_CHANGED, (int)state); |
| | | |
| | | // 连上之后发S1F1 |
| | | // 修改为不主动发送,而是响应 |
| | | // 连上之后发S1F1 |
| | | // 修改为不主动发送,而是响应 |
| | | /* |
| | | if (STATE::SELECTED == state) { |
| | | m_bAreYouThereRequest = FALSE; |
| | |
| | | HEADER* pHeader = pMessage->getHeader(); |
| | | int nStream = (pHeader->stream & 0x7F); |
| | | |
| | | LOGI("<HSMS>收到消息 S%dF%d", nStream, pHeader->function); |
| | | LOGI("<HSMS>收到消息 S%dF%d", nStream, pHeader->function); |
| | | if (nStream == 1 && pHeader->function == 1) { |
| | | // S1F1 |
| | | replyAreYouThere(pMessage); |
| | |
| | | listener.funError = onError; |
| | | m_pPassive->setListener(listener); |
| | | |
| | | // 启动工作线程 |
| | | // 启动工作线程 |
| | | m_bCimWorking = TRUE; |
| | | m_hCimWorkThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::CimWorkThreadFunction, this, |
| | | 0, &m_nCimWorkThrdaddr); |
| | |
| | | |
| | | int CHsmsPassive::term() |
| | | { |
| | | // 结束线程 |
| | | // 结束线程 |
| | | m_bCimWorking = FALSE; |
| | | SetEvent(m_hCimWorkEvent); |
| | | if (m_hCimWorkThreadHandle != NULL) { |
| | |
| | | { |
| | | while (m_bCimWorking) { |
| | | |
| | | // 待退出信号或时间到 |
| | | // 待退出信号或时间到 |
| | | int nRet = WaitForSingleObject(m_hCimWorkEvent, INFINITE); |
| | | ResetEvent(m_hCimWorkEvent); |
| | | if (!m_bCimWorking) break; |
| | | |
| | | // 取出请求列表并进行处理 |
| | | // 取出请求列表并进行处理 |
| | | std::list<CHsmsAction*> list; |
| | | Lock(); |
| | | list.splice(list.end(), m_listAction); |
| | |
| | | LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId); |
| | | |
| | | if (pAction->isNeedWaitReply()) { |
| | | // 如果需要等待回复 |
| | | // 如果需要等待回复 |
| | | int nRet = WaitForSingleObject(pAction->getEvent(), pAction->getTimeout() * 1000); |
| | | if (nRet == WAIT_TIMEOUT) { |
| | | TRACE("Timeout...\n"); |
| | | CContext* pContext = pAction->getContext(); |
| | | if (pContext != NULL) { |
| | | //pContext->setRetCode(CRC_TIMEOUT); |
| | | //pContext->setRetMsg("超时"); |
| | | //pContext->setRetMsg("超时"); |
| | | //pContext->setEvent(); |
| | | } |
| | | } |
| | |
| | | return 0; |
| | | } |
| | | |
| | | // 通用的reply ack函数 |
| | | // 通用的reply ack函数 |
| | | void CHsmsPassive::replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName) |
| | | { |
| | | IMessage* pMessage = NULL; |
| | |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来获取机器常量值 |
| | | // 交由上层应用来获取机器常量值 |
| | | if (m_listener.onEQOffLine != nullptr) { |
| | | m_listener.onEQOffLine(this); |
| | | } |
| | | |
| | | |
| | | // 回复 |
| | | // 回复 |
| | | replyAck(1, 16, pRecv->getHeader()->systemBytes, BYTE(0), "OFLACK"); |
| | | return 0; |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来获取机器常量值 |
| | | // 交由上层应用来获取机器常量值 |
| | | if (m_listener.onEQOnLine != nullptr) { |
| | | m_listener.onEQOnLine(this); |
| | | } |
| | | |
| | | |
| | | // 回复 |
| | | // 回复 |
| | | replyAck(1, 18, pRecv->getHeader()->systemBytes, BYTE(0), "ONLACK"); |
| | | return 0; |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // 要获取的常量表表 |
| | | // 要获取的常量表表 |
| | | BOOL bCheckData = FALSE; |
| | | std::vector<EQConstant> eqcs; |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来获取机器常量值 |
| | | // 交由上层应用来获取机器常量值 |
| | | if (m_listener.onEQConstantRequest != nullptr) { |
| | | m_listener.onEQConstantRequest(this, eqcs); |
| | | } |
| | | |
| | | |
| | | // 回复 |
| | | // 回复 |
| | | IMessage* pMessage = NULL; |
| | | HSMS_Create1Message(pMessage, m_nSessionId, 1, 14, pRecv->getHeader()->systemBytes); |
| | | ASSERT(pMessage); |
| | |
| | | } |
| | | |
| | | |
| | | // 要设置的常量表表 |
| | | // 要设置的常量表表 |
| | | BOOL bCheckData = FALSE; |
| | | std::vector<EQConstant> eqcs; |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | // 交由上层应用来保存和设置机器常量值 |
| | | // 交由上层应用来保存和设置机器常量值 |
| | | std::vector<unsigned int> ecvs; |
| | | if (m_listener.onEQConstantSend != nullptr) { |
| | | m_listener.onEQConstantSend(this, eqcs); |
| | | } |
| | | |
| | | |
| | | // 回复 |
| | | // 回复 |
| | | replyAck(2, 16, pRecv->getHeader()->systemBytes, BYTE(0), "EACK"); |
| | | return 0; |
| | | } |
| | |
| | | if (pBody == nullptr || pBody->getType() != SITYPE::A) ER_PARAM_ERROR; |
| | | const char* pszMessage; |
| | | if (pBody->getString(pszMessage)) { |
| | | // 更新时间 |
| | | // 更新时间 |
| | | SYSTEMTIME time; |
| | | char szBuffer[20]; |
| | | memcpy(szBuffer, pszMessage, 16); |
| | |
| | | |
| | | |
| | | MYREPLY: |
| | | // 检验结果是否正确 |
| | | // 检验结果是否正确 |
| | | for (auto item : m_mapValueIdToPRTID) { |
| | | LOGE("=== vid:%d, prtid:%d", item.first, item.second); |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // 检验结果是否正确 |
| | | // 检验结果是否正确 |
| | | for (auto item : m_mapReportIdToCEID) { |
| | | LOGE("=== prtid:%d, ceid:%d", item.first, item.second); |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // 回调到应用层 |
| | | // 回调到应用层 |
| | | if (bCheckData) { |
| | | if (m_listener.onCommand != nullptr) { |
| | | m_listener.onCommand(this, pszCmdName, params); |