| | |
| | | } |
| | | } |
| | | |
| | | bool CHsmsPassive::shouldSpool(uint8_t streamId, uint8_t functionId) const |
| | | { |
| | | // Comment: stream 1 is not spooled |
| | | if (streamId == 1) return false; |
| | | |
| | | // Comment: m=0 turns off all streams and fns |
| | | if (!m_spoolingEnabled) return false; |
| | | |
| | | // Blacklist semantics: in map => do NOT spool/cache. |
| | | // Not in map => allow spooling by default. |
| | | auto it = m_spoolBlacklistByStream.find(streamId); |
| | | if (it == m_spoolBlacklistByStream.end()) return true; |
| | | |
| | | // Empty set => all functions in this stream |
| | | if (it->second.empty()) return true; |
| | | |
| | | return it->second.find(functionId) == it->second.end(); |
| | | } |
| | | |
| | | SERVO::CReport* CHsmsPassive::defineReport(unsigned int RPTID, std::vector<unsigned int>& vids) |
| | | { |
| | | LOGI("<CHsmsPassive>defineReport enter"); |
| | | // 添加定义report |
| | | SERVO::CReport* pReport = new SERVO::CReport(RPTID, vids); |
| | | for (auto vid : vids) { |
| | | SERVO::CVariable* pVariable = getVariable(vid); |
| | | if (pVariable != nullptr) { |
| | | pReport->addVariable(pVariable); |
| | | LOGI("<CHsmsPassive>defineReport RPTID=%d", RPTID); |
| | | } |
| | | } |
| | | m_reports.push_back(pReport); |
| | | writeReportsToFile(m_strReportFilepath); |
| | | |
| | | return pReport; |
| | | } |
| | |
| | | |
| | | int CHsmsPassive::deleteReport(int rptid) |
| | | { |
| | | LOGI("<CHsmsPassive>deleteReport enter"); |
| | | if (!removeReport(rptid)) { |
| | | return -1; |
| | | } |
| | | LOGI("<CHsmsPassive>delete Report. rptid=%d", rptid); |
| | | |
| | | return writeReportsToFile(m_strReportFilepath); |
| | | } |
| | | |
| | |
| | | return -1; |
| | | } |
| | | |
| | | void CHsmsPassive::clearAllReport() |
| | | void CHsmsPassive::clearAllReport(BOOL bSave/* = FALSE*/) |
| | | { |
| | | LOGI("<CHsmsPassive>clearAllReport enter"); |
| | | for (auto item : m_reports) { |
| | | delete item; |
| | | } |
| | | m_reports.clear(); |
| | | |
| | | if(bSave) |
| | | writeReportsToFile(m_strReportFilepath); |
| | | } |
| | | |
| | | int CHsmsPassive::writeReportsToFile(const std::string& filepath) |
| | |
| | | int CHsmsPassive::serialize(char* pszBuffer, int nBufferSize) |
| | | { |
| | | int index = 0; |
| | | const auto calcSpoolCfgSize = [&]() -> int { |
| | | // magic(4) + ver(2) + enabled(1) + mapSize(4) + entries... |
| | | int sz = 0; |
| | | sz += 4; // 'SPOL' |
| | | sz += 2; // version |
| | | sz += 1; // enabled |
| | | sz += 4; // map size |
| | | for (const auto& kv : m_spoolBlacklistByStream) { |
| | | sz += 2; // streamId (U16) |
| | | sz += 4; // fn count (U32) |
| | | sz += static_cast<int>(kv.second.size()) * 2; // fn ids (U16 each) |
| | | } |
| | | return sz; |
| | | }; |
| | | if (pszBuffer == nullptr) { |
| | | index += sizeof(int); |
| | | for (auto item : m_listActionSpooling) { |
| | | index += item->serialize(pszBuffer, nBufferSize); |
| | | } |
| | | |
| | | index += calcSpoolCfgSize(); |
| | | |
| | | return index; |
| | | } |
| | |
| | | nRet = item->serialize(&pszBuffer[index], nBufferSize); |
| | | if (nRet <= 0) break; |
| | | index += nRet; |
| | | } |
| | | |
| | | // Append spooling config (backward compatible via magic+version) |
| | | auto writeU32 = [&](uint32_t v) { |
| | | memcpy(&pszBuffer[index], &v, sizeof(v)); |
| | | index += sizeof(v); |
| | | }; |
| | | auto writeU16 = [&](uint16_t v) { |
| | | memcpy(&pszBuffer[index], &v, sizeof(v)); |
| | | index += sizeof(v); |
| | | }; |
| | | auto writeU8 = [&](uint8_t v) { |
| | | memcpy(&pszBuffer[index], &v, sizeof(v)); |
| | | index += sizeof(v); |
| | | }; |
| | | |
| | | const uint32_t magic = 0x4C4F5053; // 'SPOL' little-endian |
| | | writeU32(magic); |
| | | writeU16(1); // version |
| | | writeU8(m_spoolingEnabled ? 1 : 0); |
| | | writeU32(static_cast<uint32_t>(m_spoolBlacklistByStream.size())); |
| | | for (const auto& kv : m_spoolBlacklistByStream) { |
| | | writeU16(static_cast<uint16_t>(kv.first)); |
| | | writeU32(static_cast<uint32_t>(kv.second.size())); |
| | | for (const auto& fn : kv.second) { |
| | | writeU16(static_cast<uint16_t>(fn)); |
| | | } |
| | | } |
| | | |
| | | return index; |
| | |
| | | m_listActionSpooling.push_back(pAction); |
| | | } |
| | | |
| | | return index + nRet; |
| | | // Parse optional spooling config tail (magic+version). If absent, keep defaults. |
| | | const auto remaining = nBufferSize - index; |
| | | if (remaining >= 4) { |
| | | uint32_t magic = 0; |
| | | memcpy(&magic, &pszBuffer[index], sizeof(magic)); |
| | | if (magic == 0x4C4F5053) { // 'SPOL' |
| | | index += 4; |
| | | if (nBufferSize - index >= 2 + 1 + 4) { |
| | | uint16_t ver = 0; |
| | | memcpy(&ver, &pszBuffer[index], sizeof(ver)); |
| | | index += 2; |
| | | if (ver >= 1) { |
| | | uint8_t enabled = 1; |
| | | memcpy(&enabled, &pszBuffer[index], sizeof(enabled)); |
| | | index += 1; |
| | | m_spoolingEnabled = (enabled != 0); |
| | | |
| | | uint32_t mapSize = 0; |
| | | memcpy(&mapSize, &pszBuffer[index], sizeof(mapSize)); |
| | | index += 4; |
| | | |
| | | m_spoolBlacklistByStream.clear(); |
| | | for (uint32_t mi = 0; mi < mapSize; ++mi) { |
| | | if (nBufferSize - index < 2 + 4) break; |
| | | uint16_t streamId = 0; |
| | | memcpy(&streamId, &pszBuffer[index], sizeof(streamId)); |
| | | index += 2; |
| | | uint32_t fnCount = 0; |
| | | memcpy(&fnCount, &pszBuffer[index], sizeof(fnCount)); |
| | | index += 4; |
| | | |
| | | auto& setRef = m_spoolBlacklistByStream[streamId]; |
| | | setRef.clear(); |
| | | for (uint32_t fi = 0; fi < fnCount; ++fi) { |
| | | if (nBufferSize - index < 2) break; |
| | | uint16_t fn = 0; |
| | | memcpy(&fn, &pszBuffer[index], sizeof(fn)); |
| | | index += 2; |
| | | setRef.insert(fn); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return index; |
| | | } |
| | | |
| | | unsigned CHsmsPassive::OnCimWork() |
| | |
| | | Unlock(); |
| | | |
| | | while (!list.empty()) { |
| | | CHsmsAction* pAction = nullptr; |
| | | Lock(); |
| | | CHsmsAction* pAction = list.front(); |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | | m_listActionSpooling.push_back(pAction); |
| | | Unlock(); |
| | | continue; |
| | | } |
| | | pAction = list.front(); |
| | | Unlock(); |
| | | list.pop_front(); |
| | | |
| | | Lock(); |
| | | const bool selected = (m_pPassive != NULL && STATE::SELECTED == m_pPassive->getState()); |
| | | Unlock(); |
| | | if (!selected) { |
| | | IMessage* pMsg = pAction->getSendMessage(); |
| | | uint8_t streamId = 0; |
| | | uint8_t functionId = 0; |
| | | if (pMsg && pMsg->getHeader()) { |
| | | streamId = static_cast<uint8_t>(pMsg->getHeader()->stream & 0x7F); |
| | | functionId = static_cast<uint8_t>(pMsg->getHeader()->function & 0xFF); |
| | | } |
| | | if (shouldSpool(streamId, functionId)) { |
| | | Lock(); |
| | | m_listActionSpooling.push_back(pAction); |
| | | Unlock(); |
| | | } |
| | | else { |
| | | LOGI("<HSMS>spooling disabled for S%dF%d, drop action", (int)streamId, (int)functionId); |
| | | delete pAction; |
| | | } |
| | | continue; |
| | | } |
| | | TRACE("OnCimWork 004.\n"); |
| | | |
| | | if (pAction->isNeedWaitReply()) { |
| | |
| | | rptListItem = pBody->getSubItem(1); |
| | | if (rptListItem == nullptr) goto MYREPLY; |
| | | if (rptListItem->getSubItemSize() == 0) { |
| | | clearAllReport(); |
| | | clearAllReport(TRUE); |
| | | goto MYREPLY; |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | if (vids.empty()) { |
| | | deleteReport(rptid); |
| | | } else { |
| | | removeReport(rptid); |
| | | if (!vids.empty()) { |
| | | pReport = defineReport(rptid, vids); |
| | | } |
| | | |
| | |
| | | |
| | | // 清空所有 |
| | | if (pBody->getSubItemSize() == 0) { |
| | | m_spoolingConfig.clear(); |
| | | LOGI("<CHsmsPassive>turns off all streams and fns"); |
| | | m_spoolBlacklistByStream.clear(); |
| | | m_spoolingEnabled = false; |
| | | goto MYREPLY; |
| | | } |
| | | m_spoolingEnabled = true; |
| | | |
| | | // 依次配置Stream |
| | | for (int i = 0; i < pBody->getSubItemSize(); i++) { |
| | |
| | | unsigned char STRID, FCNID; |
| | | pStreamItem->getSubItemU1(0, STRID); |
| | | ISECS2Item* pFcnItemList = pStreamItem->getSubItem(1); |
| | | if (pFcnItemList->getSubItemSize() == 0) { |
| | | m_spoolingConfig[STRID].clear(); |
| | | if (pFcnItemList == nullptr || pFcnItemList->getSubItemSize() == 0) { |
| | | // No functions listed => blacklist the whole stream |
| | | m_spoolBlacklistByStream[STRID].clear(); |
| | | } |
| | | else { |
| | | // Update blacklist for this stream |
| | | m_spoolBlacklistByStream[STRID].clear(); |
| | | for (int j = 0; j < pFcnItemList->getSubItemSize(); j++) { |
| | | pFcnItemList->getSubItemU1(j, FCNID); |
| | | m_spoolingConfig[STRID].insert(FCNID); |
| | | m_spoolBlacklistByStream[STRID].insert(FCNID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 打印验证结果 |
| | | for (auto s : m_spoolingConfig) { |
| | | LOGI("====> stream:%d", s.first); |
| | | for (auto s : m_spoolBlacklistByStream) { |
| | | LOGI("====> spool blacklist stream:%d", s.first); |
| | | if (s.second.empty()) { |
| | | LOGI("blacklist all functions"); |
| | | } |
| | | else { |
| | | for (auto f : s.second) { |
| | | LOGI("function:%d", f); |
| | | LOGI("blacklist function:%d", f); |
| | | } |
| | | } |
| | | } |
| | | MYREPLY: |
| | |
| | | |
| | | // 丢弃 |
| | | if (RSDC == 1) { |
| | | LOGI("<CHsmsPassive>Purge Spooled Data."); |
| | | Lock(); |
| | | for (auto item : m_listActionSpooling) { |
| | | delete item; |
| | |
| | | Unlock(); |
| | | } |
| | | else { |
| | | LOGI("<CHsmsPassive>Request Spooled Data."); |
| | | Lock(); |
| | | for (auto item : m_listActionSpooling) { |
| | | m_listAction.push_back(item); |
| | |
| | | pItem->addItem(ALTX, "ALTX"); |
| | | pAction->setSendMessage(pMessage); |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | | if (shouldSpool(5, 1)) { |
| | | m_listActionSpooling.push_back(pAction); |
| | | } |
| | | else { |
| | | LOGI("<HSMS>spooling disabled for S5F1, drop alarm report"); |
| | | delete pAction; |
| | | } |
| | | } |
| | | else { |
| | | m_listAction.push_back(pAction); |
| | |
| | | } |
| | | pAction->setSendMessage(pMessage); |
| | | if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) { |
| | | if (shouldSpool(6, 11)) { |
| | | m_listActionSpooling.push_back(pAction); |
| | | } |
| | | else { |
| | | LOGI("<HSMS>spooling disabled for S6F11, drop event report (CEID=%u)", CEID); |
| | | delete pAction; |
| | | } |
| | | } |
| | | else { |
| | | m_listAction.push_back(pAction); |
| | | SetEvent(m_hCimWorkEvent); |
| | | } |