#include "stdafx.h" #include "AlarmFSM.h" #include "Event.h" #include "CommEntityRestful.hpp" #include "json/json.h" namespace Task { //发送告警 struct SendAlarmTask : public ITaskSp{ AlarmFSM* m_fsm; explicit SendAlarmTask(AlarmFSM* f) : m_fsm(f) {} void Process(){ LOG_FUNCTION(); //改为循环处理告警 int logSum=0; while(true){ if(m_fsm->m_NewUploading_alarm.empty()&&m_fsm->m_unSendAlarm.IsNullOrEmpty()){ if(logSum>=1200){ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("no warn,wait 1 hour"); logSum=0; }else{ logSum++; } Sleep(3000);//无重发和新的告警则等待 continue; } logSum=0; #ifdef RVC_OS_WIN IHttpFunc* client; client = create_http(m_fsm->HttpsLogCallBack); bool isSendSucc=false;//查询是否成功标志 if(SendAlarmTaskImpl(client)){ isSendSucc = true; }else{ isSendSucc = false; } client->Destory(); #else bool isSendSucc=false;//查询是否成功标志 if(SendAlarmTaskImpl()){ isSendSucc = true; }else{ isSendSucc = false; } #endif //m_fsm->PostEventFIFO(new SendAlarmEvent(isSendSucc));//返回处理结果 if(isSendSucc){ //成功 //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("send alarm statistic m_iRec=%d , m_iThrow=%d , UnSend=%d , m_iSucc=%d , m_iFail=%d",m_fsm->m_iRec,m_fsm->m_iThrow,m_fsm->m_NewUploading_alarm.size(),m_fsm->m_iSucc,m_fsm->m_iFail); if(!m_fsm->m_NewUploading_alarm.empty()){ Sleep(2000);//赶紧发送 continue; }else{ Sleep(3000);//等待 continue; } }else{ //失败,超过未发送成功的告警时间间隔,丢弃告警信息 CSmallDateTime endTime = CSmallDateTime::GetNow(); if(((DWORD)endTime-(DWORD)m_fsm->m_sendBeginTime)>m_fsm->m_maxResendTime){ m_fsm->m_unSendAlarm="";//置为空 m_fsm->m_iFail = m_fsm->m_iFail+ m_fsm->m_eachSum ;//发送失败 LogWarn(Severity_Low,Error_Exception,WARN_ALARM_SEND_FAIL,CSimpleStringA::Format("throw away alarm num= %d,m_iFail=%d,m_iThrow=%d",m_fsm->m_eachSum,m_fsm->m_iFail,m_fsm->m_iThrow)); m_fsm->m_eachSum =0;//清空批次数量 m_fsm->m_sendBeginTime = CSmallDateTime::GetNow(); DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("send alarm statistic m_iRec=%d , m_iThrow=%d , UnSend=%d , m_iSucc=%d , m_iFail=%d",m_fsm->m_iRec,m_fsm->m_iThrow,m_fsm->m_NewUploading_alarm.size(),m_fsm->m_iSucc,m_fsm->m_iFail); } Sleep(20*1000);//失败重发等待 continue; } } } #ifdef RVC_OS_WIN bool SendAlarmTaskImpl(IHttpFunc* client){ HttpStruct::SendAlarmTaskReq qTempReq; HttpStruct::SendAlarmTaskRet qTempRet; if(m_fsm->m_unSendAlarm.IsNullOrEmpty()){ //组装新的json告警信息 string strJson = m_fsm->alarmJson(); if(strJson.empty()){ return true; }else{ qTempReq.m_reqStr = strJson.c_str();//请求参数 m_fsm->m_unSendAlarm = strJson.c_str(); m_fsm->m_sendBeginTime = CSmallDateTime::GetNow(); } }else{ //重发新的告警信息 qTempReq.m_reqStr = m_fsm->m_unSendAlarm.GetData();//请求参数 DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("alarm retry send"); } qTempReq.m_url=m_fsm->m_sendUrl.GetData();//访问地址 //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("alarm send =%s",qTempReq.m_reqStr.c_str()); PROCESS_LINK_CONTEXT("LR0402107SendAlarmTask") if(!client->Post(qTempReq, qTempRet, &nextLink)){ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask http req fail,url=%s",qTempReq.m_url.c_str()); return false;//失败 } Json::Reader reader; Json::Value rootRet; if (!reader.parse(qTempRet.m_retStr, rootRet, false)) { DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask parse resp is fail"); return false;//失败 } bool isSucc = rootRet["success"].asBool(); if(isSucc){ //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is succ,m_eachSum=%d",m_fsm->m_eachSum); m_fsm->m_unSendAlarm="";//置为空 m_fsm->m_iSucc = m_fsm->m_iSucc+ m_fsm->m_eachSum ;//发送成功 m_fsm->m_eachSum = 0;//清空批次数量 return true;//写入成功 }else{ CSimpleStringA errCode = rootRet["code"].asString().c_str(); if(!errCode.IsNullOrEmpty()||errCode == "10101"){ //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is false,code = 10101"); m_fsm->m_unSendAlarm="";//置为空 m_fsm->m_iFail = m_fsm->m_iFail+ m_fsm->m_eachSum ;//发送失败 LogWarn(Severity_Low,Error_Exception,WARN_ALARM_PARSE_FAIL,CSimpleStringA::Format("SendAlarmTask [success] is false,code = 10101,throw away alarm num= %d,m_iFail=%d",m_fsm->m_eachSum,m_fsm->m_iFail)); m_fsm->m_eachSum = 0;//清空批次数量 return true;//中文乱码解析失败,默认成功 }else{ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is false,code =%s",errCode); return false;//写入失败 } } } #else bool SendAlarmTaskImpl() { HttpClientResponseResult result; HttpClientRequestConfig config(HttpRequestMethod::POST, m_fsm->m_sendUrl.GetData(), &SpGetToken); string reqStr = ""; if(m_fsm->m_unSendAlarm.IsNullOrEmpty()){ //组装新的json告警信息 string strJson = m_fsm->alarmJson(); if(strJson.empty()){ return true; }else{ reqStr = strJson.c_str();//请求参数 m_fsm->m_unSendAlarm = strJson.c_str(); m_fsm->m_sendBeginTime = CSmallDateTime::GetNow(); } }else{ //重发新的告警信息 reqStr = m_fsm->m_unSendAlarm.GetData();//请求参数 DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("alarm retry send"); } config.SetJsonBody(reqStr); RestfulClient client = RestfulClient::getInstance(); PROCESS_LINK_CONTEXT("LR0402107SendAlarmTask"); config.PreDo(); client.Do(&config, &result, &nextLink); //判断结果 if(result.ResponseOK()){ //解析返回字符串 Json::Reader reader; Json::Value rootRet; if (!reader.parse(result.content, rootRet, false)) { DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask parse resp is fail"); return false;//失败 } bool isSucc = rootRet["success"].asBool(); if(isSucc){ //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is succ,m_eachSum=%d",m_fsm->m_eachSum); m_fsm->m_unSendAlarm="";//置为空 m_fsm->m_iSucc = m_fsm->m_iSucc+ m_fsm->m_eachSum ;//发送成功 m_fsm->m_eachSum = 0;//清空批次数量 return true;//写入成功 }else{ CSimpleStringA errCode = rootRet["code"].asString().c_str(); if(!errCode.IsNullOrEmpty()||errCode == "10101"){ //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is false,code = 10101"); m_fsm->m_unSendAlarm="";//置为空 m_fsm->m_iFail = m_fsm->m_iFail+ m_fsm->m_eachSum ;//发送失败 LogWarn(Severity_Low,Error_Exception,WARN_ALARM_PARSE_FAIL,CSimpleStringA::Format("SendAlarmTask [success] is false,code = 10101,throw away alarm num= %d,m_iFail=%d",m_fsm->m_eachSum,m_fsm->m_iFail)); m_fsm->m_eachSum = 0;//清空批次数量 return true;//中文乱码解析失败,默认成功 }else{ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask [success] is false,code =%s",errCode); return false;//写入失败 } } } else { std::string errDetail(result.WhatError()); DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SendAlarmTask http req fail,error=[%s],url=%s", errDetail.c_str(), m_fsm->m_sendUrl.GetData()); return false;//失败 } return true; } #endif }; } AlarmFSM::AlarmFSM() { InitializeCriticalSection(&cs); INIT_LIST_HEAD(&m_uploading_alarm); INIT_LIST_HEAD(&m_uploaded_alarm); m_iEachSend=0;//每次连接发送的数量 m_iRec=0;//累计收到的告警数目 m_iSend=0;//累计队列发送总数 m_iThrow=0;//累计队列丢弃总数 m_iFail=0;//累计发送失败总次数 m_iSucc=0;//累计发送成功总次数 m_CenterModel=2; m_maxResendTime=120; m_eachSum=0; m_initAlarm=false; } AlarmFSM::~AlarmFSM() { DeleteCriticalSection(&cs); } void AlarmFSM::OnStateTrans( int iSrcState, int iDstState ) { DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState)); } void AlarmFSM::OnSysVarEvent( const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName ) { } ErrorCodeEnum AlarmFSM::OnInit() { AddStateHooker(this); //...... CSmartPointer spFunction = m_pEntity->GetFunction(); CSmartPointer spConfig; ErrorCodeEnum Error = spFunction->OpenConfig(Config_CenterSetting, spConfig); if (Error_Succeed == Error) { Error = spConfig->ReadConfigValueInt("Alarm", "DealWarningTime", m_nDealWarningTime); if (Error_Succeed == Error) { DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("get DealWarningTime=%d from CenterSetting.ini", m_nDealWarningTime); } else { DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("get DealWarningTime from CenterSetting.ini failed"); } m_CenterModel = 2; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init use default value CenterModel=2"); int maxResendTime = 120; Error = spConfig->ReadConfigValueInt("Alarm", "maxResendTime", maxResendTime); if(Error==Error_Succeed){ if (maxResendTime > 0) { m_maxResendTime = maxResendTime; } else { m_maxResendTime = 120; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini maxResendTime=%d", m_maxResendTime); }else{ DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini maxResendTime failed"); } CSimpleStringA str=""; Error = spConfig->ReadConfigValue("Alarm", "topic", str); if(Error==Error_Succeed){ m_topic = str; DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini topic=%s",str.GetData()); }else{ DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini topic failed"); } Error = spConfig->ReadConfigValue("Alarm", "sendUrl", str); if(Error==Error_Succeed){ m_sendUrl = str; DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini sendUrl=%s",str.GetData()); }else{ DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini sendUrl failed"); } Error = spConfig->ReadConfigValue("Alarm", "branchNo", str); if(Error==Error_Succeed){ m_branchNo = str; DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini branchNo=%s",str.GetData()); }else{ DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("init read CenterSetting.ini branchNo failed"); } } else { DbgWithLink(LOG_LEVEL_WARN,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("open CenterSetting.ini failed"); } if (m_nDealWarningTime == 0) { m_nDealWarningTime = 10; } if(m_branchNo.IsNullOrEmpty()){ m_branchNo = "000";//默认是000总行分行号 } return Error_Succeed; } ErrorCodeEnum AlarmFSM::OnExit() { return Error_Succeed; } void AlarmFSM::s0_on_entry() { if(!m_initAlarm){ m_initAlarm=true; LogWarn(Severity_Low,Error_Exception,WARN_ALARM_START_NEW_MODE,CSimpleStringA::Format("init alarm new model,model=%d",m_CenterModel)); } //新模式 PostEventLIFO(new FSMEvent(USER_EVT_JMP_NEW_ALARM));//跳转新模式发送 } void AlarmFSM::s0_on_exit() { CancelTimer(1); CancelTimer(2); } unsigned int AlarmFSM::s0_on_event( FSMEvent* event ) { if (event->iEvt == EVT_TIMER) { if(event->param1 == 2){ //开始启动调用发送线程 Task::SendAlarmTask* alarmTask = new Task::SendAlarmTask(this); ErrorCodeEnum rc = m_pEntity->GetFunction()->PostThreadPoolTask(alarmTask); if(rc!=Error_Succeed){ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("s0 create SendAlarmTask is fail,%d",(int)rc); ScheduleTimer(2, 10*1000);//等待一段时间 } } }else if (event->iEvt == USER_EVT_JMP_NEW_ALARM){ //开始启动调用发送线程 Task::SendAlarmTask* alarmTask = new Task::SendAlarmTask(this); ErrorCodeEnum rc = m_pEntity->GetFunction()->PostThreadPoolTask(alarmTask); if(rc!=Error_Succeed){ DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("s0 create SendAlarmTask is fail,%d",(int)rc); ScheduleTimer(2, 10*1000);//等待一段时间 } } return 0; } void AlarmFSM::s1_on_entry() { } void AlarmFSM::s1_on_exit() { CancelTimer(2); } unsigned int AlarmFSM::s1_on_event(FSMEvent* event) { return 0; } void AlarmFSM::s2_on_entry() { } void AlarmFSM::s2_on_exit() { } unsigned int AlarmFSM::s2_on_event(FSMEvent* event) { return 0; } void AlarmFSM::s3_on_entry() { } void AlarmFSM::s3_on_exit() { } unsigned int AlarmFSM::s3_on_event(FSMEvent* event) { return 0; } static time_t NowTime() { time_t t_Now = time(0); struct tm* tm_Now = localtime(&t_Now); /*tm_Now->tm_hour =0; tm_Now->tm_min = 0; tm_Now->tm_sec = 0;*/ return mktime(tm_Now); } //增加消息到新告警列表 void AlarmFSM::add_NewAlarm(alarm_t* alarm) { EnterCriticalSection(&cs); if(m_NewUploading_alarm.size()>=UPLOG_MAX_COUNT){ m_iThrow++; alarm_t* oldAlarm = (alarm_t*)(*m_NewUploading_alarm.begin());//集合首个元素 m_NewUploading_alarm.erase(m_NewUploading_alarm.begin());//集合删除首元素 free(oldAlarm->Description); oldAlarm->Description=NULL; free(oldAlarm->EntityName); oldAlarm->EntityName=NULL; free(oldAlarm->SN); oldAlarm->SN=NULL; free(oldAlarm->warnTime); oldAlarm->warnTime=NULL; delete oldAlarm; oldAlarm=NULL; } m_NewUploading_alarm.push_back(alarm);//加入队列 LeaveCriticalSection(&cs); } //取出消息从新告警列表 alarm_t* AlarmFSM::removeAlarm() {//加锁,取出先进的队列日志,注意释放内存空间 alarm_t* dAlarm = NULL; EnterCriticalSection(&cs); if(m_NewUploading_alarm.empty()){ //return NULL; }else{ dAlarm = (alarm_t*)(*m_NewUploading_alarm.begin());//集合首个元素 m_NewUploading_alarm.erase(m_NewUploading_alarm.begin());//集合删除首元素 } LeaveCriticalSection(&cs); return dAlarm;//返回 } void AlarmFSM::HttpsLogCallBack(const char* logtxt) { DbgWithLink(LOG_LEVEL_DEBUG,LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("http dbg: %s",logtxt); } std::string AlarmFSM::alarmJson() { vector unSendAlarm; string jsonStr =""; EnterCriticalSection(&cs); alarm_t* dAlarm = NULL; for(int i = 0 ;i<16;i++){ if(m_NewUploading_alarm.empty()){ break; }else{ dAlarm = (alarm_t*)(*m_NewUploading_alarm.begin());//集合首个元素 m_NewUploading_alarm.erase(m_NewUploading_alarm.begin());//集合删除首元素 unSendAlarm.push_back(dAlarm); } } LeaveCriticalSection(&cs); if(unSendAlarm.size()==0){ return jsonStr;//无发送直接返回空 } Json::Value root; Json::Value arraylist;//消息列表 Json::FastWriter fw;//写入对象 int i = 0; CSystemStaticInfo si; { m_pEntity->GetFunction()->GetSystemStaticInfo(si); } for(auto iter = unSendAlarm.begin(); iter!=unSendAlarm.end(); iter++){ Json::Value rootAlarm; Json::FastWriter fwAlarm;//写入对象 alarm_t* alarmt = *iter; m_uuid =CUUID::Create(m_uuid); rootAlarm["IDKey"] = m_uuid.ToString().GetData(); rootAlarm["BranchNo"] = m_branchNo.GetData(); rootAlarm["TerminalNo"] = si.strTerminalID.GetData(); rootAlarm["EntityName"] = alarmt->EntityName; rootAlarm["Item"] = CSimpleStringA::Format("%016llx", alarmt->Item).SubString(8,8).GetData();//16进制取后面八位 char Level[2]; sprintf(Level, "%c", alarmt->Level); rootAlarm["Level"] = CSimpleStringA::Format("%s",Level).GetData(); rootAlarm["LifeID"] = CSimpleStringA::Format("%016llx", alarmt->LifeID).SubString(8,8).GetData();//16进制取后面八位 rootAlarm["SN"] = alarmt->SN; rootAlarm["UserCode"] = CSimpleStringA::Format("%016llx", alarmt->UserCode).SubString(8,8).GetData();//16进制取后面八位 rootAlarm["WarningTime"] = CSimpleStringA::Format("%s", alarmt->warnTime).GetData(); rootAlarm["Description"] = CSimpleStringA::Format("%s", alarmt->Description).GetData(); //增加终端版本号字段 rootAlarm["VersionNo"] = si.InstallVersion.ToString().GetData(); string alarmJsonStr = fwAlarm.write(rootAlarm); //DbgWithLink(LOG_LEVEL_INFO,LOG_TYPE_SYSTEM)("alarmJsonStr=%s",alarmJsonStr.c_str()); arraylist[i]=alarmJsonStr.c_str(); i++; } root["message_list"] = arraylist; root["topic"]=m_topic.GetData(); jsonStr = fw.write(root); m_eachSum = i; //清理内存 while(true){ if(unSendAlarm.empty()){ break; }else{ dAlarm = (alarm_t*)(*unSendAlarm.begin());//集合首个元素 unSendAlarm.erase(unSendAlarm.begin());//集合删除首元素 } free(dAlarm->Description); dAlarm->Description=NULL; free(dAlarm->EntityName); dAlarm->EntityName=NULL; free(dAlarm->SN); dAlarm->SN=NULL; free(dAlarm->warnTime); dAlarm->warnTime=NULL; delete dAlarm; dAlarm=NULL; } return jsonStr; }