⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 record.cpp

📁 高速公路收费系统车道软件. 功能: 1 检测公路过往车辆 2 收费过程控制和数据采集 3 车辆信息和图片上传服务器.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	sprintf(strMH_Info+MH_MODIFY_COUNT,"%.4d",m_clsStat.MhModifyCount());
	sprintf(strMH_Info+MH_LOOP_COUNT,"%.4d",m_clsStat.MhLoopCount());
	sprintf(strMH_Info+MH_TOTAL_MONEY,"%.6u",m_clsStat.MhTotalMoney());
	sprintf(strMH_Info+MH_BAD_INVOICE_MONEY,"%.6u",m_clsStat.MhBadMoney());
	//收费车车流
	sprintf(strMH_Info+MH_NORMAL_TOTAL_COUNT,"%.4d",m_clsStat.MhTypeCount(TYPE_NORMAL));
	for(i=0;i<9;i++)
	{
		memset(tmpStr,0,8);
		sprintf(tmpStr,"%.4d",m_clsStat.MhClassTypeCount(i+'1',TYPE_NORMAL));
		memmove(strMH_Info+MH_NORMAL_CLASS_COUNT+i*4,tmpStr,4);
	}
	//免费车车流
	sprintf(strMH_Info+MH_FREE_TOTAL_COUNT,"%.4d",m_clsStat.MhTypeCount(TYPE_FREE));
	for(i=0;i<9;i++)
	{
		memset(tmpStr,0,8);
		sprintf(tmpStr,"%.4d",m_clsStat.MhClassTypeCount(i+'1',TYPE_FREE));
		memmove(strMH_Info+MH_FREE_CLASS_COUNT+i*4,tmpStr,4);
	}
	//月票车车流
	sprintf(strMH_Info+MH_MONTH_TOTAL_COUNT,"%.4d",m_clsStat.MhTypeCount(TYPE_MONTH));
	for(i=0;i<9;i++)
	{
		memset(tmpStr,0,8);
		sprintf(tmpStr,"%.4d",m_clsStat.MhClassTypeCount(i+'1',TYPE_MONTH));
		memmove(strMH_Info+MH_MONTH_CLASS_COUNT+i*4,tmpStr,4);
	}
	//军警车车流
	sprintf(strMH_Info+MH_ARMY_TOTAL_COUNT,"%.4d",m_clsStat.MhTypeCount(TYPE_ARMY_POLICE));
	for(i=0;i<9;i++)
	{
		memset(tmpStr,0,8);
		sprintf(tmpStr,"%.4d",m_clsStat.MhClassTypeCount(i+'1',TYPE_ARMY_POLICE));
		memmove(strMH_Info+MH_ARMY_CLASS_COUNT+i*4,tmpStr,4);
	}
	//废票数目
	sprintf(strMH_Info+MH_BAD_INVOICE_TOTAL_COUNT,"%.4d",m_clsStat.MhBadInvoiceCount());
	for(i=0;i<9;i++)
	{
		memset(tmpStr,0,8);
		sprintf(tmpStr,"%.4d",m_clsStat.MhClassBadInvoiceCount(i+1));
		memmove(strMH_Info+MH_BAD_INVOICE_CLASS_COUNT+i*4,tmpStr,4);
	}
	SaveData(MESSAGE_MH,strMH_Info,MH_LENGTH);	
}

//	生成PW消息:密码更改消息
void CRecord::RecordPW()
{
	CTransInfo m_clsTransInfo;	
	SetMesgHead("PW",MESSAGE_PW);
	char strPW_Info[PW_LENGTH+1];
	memset(strPW_Info,0,PW_LENGTH+1);
	sprintf(strPW_Info+PW_PASSWORD_NEW,"%.6u",m_clsTransInfo.NewPassword());
	SaveData(MESSAGE_PW,strPW_Info,PW_LENGTH);	
}

//	生成SM消息:汇总消息
void CRecord::RecordSM()
{	
	SetMesgHead("SM",MESSAGE_SM);
	char strSM_Info[SM_LENGTH+1];
	memset(strSM_Info,0,SM_LENGTH+1);
//	获取指定日期的索引文件名
	CLaneInfo m_clsLane;
	char strFileName[35];
	memset(strFileName,0,35);
	if(m_clsLane.RAM_Disk()){
		sprintf(strFileName,"%s\\%.2d%.3d",TEMP_PATH,nRecordYear%100,nRecordDayCount);
	} else {
		sprintf(strFileName,"%s\\%.2d%.3d",INFO_PATH,nRecordYear%100,nRecordDayCount);
	}
	UINT nMesgHeadIndex[MESSAGE_COUNT];
	memset(&nMesgHeadIndex,0,sizeof(UINT)*MESSAGE_COUNT);
	FILE *fp1;
	if((fp1=fopen(strFileName,"rb"))!=NULL){
		if(fread(&nMesgHeadIndex,sizeof(UINT),MESSAGE_COUNT,fp1)!=MESSAGE_COUNT){
			memset(&nMesgHeadIndex,0,sizeof(UINT)*MESSAGE_COUNT);
		}
		fclose(fp1);
	} else {
		memset(&nMesgHeadIndex,0,sizeof(UINT)*MESSAGE_COUNT);
	}
//	生成SM消息
	sprintf(strSM_Info+SM_SUM_TR,"%.4d",nMesgHeadIndex[MESSAGE_TR]);
	sprintf(strSM_Info+SM_SUM_ME,"%.4d",nMesgHeadIndex[MESSAGE_ME]);
	sprintf(strSM_Info+SM_SUM_BS,"%.4d",nMesgHeadIndex[MESSAGE_BS]);
	sprintf(strSM_Info+SM_SUM_ES,"%.4d",nMesgHeadIndex[MESSAGE_ES]);
	sprintf(strSM_Info+SM_SUM_MH,"%.4d",nMesgHeadIndex[MESSAGE_MH]);
	SaveData(MESSAGE_SM,strSM_Info,SM_LENGTH);
}


//	设定消息头
//	为了方便重传,消息在车道上的备份按消息类型分文件存储且使用不
//	同的文件扩展名,这样可以保证每个文件中存储的每条消息长度相同,
//	当上位机需要重传指定序号的消息时,我们只需要直接将文件指针移
//	动到对应的位置上即可

//	消息在车道上的备份文件命名规则如下:车道序号(2 byte) + 年(2 
//	byte) + 天数(3 byte) + 扩展名,其中扩展名即为消息类型
void CRecord::SetMesgHead(char *strHead,UINT nType)
{
	memset(strMesgHead,0,MESG_HEAD_LENGTH+1);
	CLaneInfo m_clsLane;
//	特别地:除小时消息外其他消息的产生时间即为当前时间,小时消息的
//			产生时间未必为当前时间(收费过程中非正点退出,重新启动
//			后小时消息时间应为退出前时间)
	CStatInfo m_clsStat;	
	CTimeInfo m_clsTime;
	memset(strBackupName,0,12);
	switch(nType){	
	case MESSAGE_EW:				//报警消息
		sprintf(strMesgHead+MESG_INDEX,"%.4d",		//消息序号
			MesgHeadIndex(nType,m_clsTime.GetYear()%100,m_clsTime.GetDayCount()));
		memmove(strMesgHead+MESG_TYPE,strHead,2);	//消息类型
		sprintf(strMesgHead+MESG_PLAZA,"%.2d",m_clsLane.PlazaNO());
//	报警消息备份文件后缀名为"W"
		sprintf(strMesgHead+MESG_YEAR,"%.2d",m_clsTime.GetYear()%100);
		sprintf(strMesgHead+MESG_DAY,"%.3d",m_clsTime.GetDayCount());
		sprintf(strMesgHead+MESG_TIME,"%.2d",m_clsTime.GetHour());
		sprintf(strMesgHead+MESG_TIME+2,"%.2d",m_clsTime.GetMinute());
		sprintf(strMesgHead+MESG_SECOND,"%.2d",m_clsTime.GetSecond());
		sprintf(strBackupName,"%.2d%.2d%.3d.w",m_clsLane.LaneNO(),
			m_clsTime.GetYear()%100,m_clsTime.GetDayCount());
		break;
	case MESSAGE_AK:				//接收文件状态消息
	case MESSAGE_TR:				//原始过车消息
	case MESSAGE_BS:				//开班消息
	case MESSAGE_ES:				//交班消息
	case MESSAGE_PW:
	case MESSAGE_ME:
//	理论上,若未交班时退出,重新启动后补交班的时间应为退出时的时间,
//	但本程序暂时没有这样处理
		sprintf(strMesgHead+MESG_INDEX,"%.4d",		//消息序号
			MesgHeadIndex(nType,m_clsTime.GetYear()%100,m_clsTime.GetDayCount()));
		memmove(strMesgHead+MESG_TYPE,strHead,2);	//消息类型
		sprintf(strMesgHead+MESG_PLAZA,"%.2d",m_clsLane.PlazaNO());
//	其他消息备份文件后缀使用相同消息类型的第一个字母
		sprintf(strMesgHead+MESG_YEAR,"%.2d",m_clsTime.GetYear()%100);
		sprintf(strMesgHead+MESG_DAY,"%.3d",m_clsTime.GetDayCount());
		sprintf(strMesgHead+MESG_TIME,"%.2d",m_clsTime.GetHour());
		sprintf(strMesgHead+MESG_TIME+2,"%.2d",m_clsTime.GetMinute());
		sprintf(strMesgHead+MESG_SECOND,"%.2d",m_clsTime.GetSecond());
		sprintf(strBackupName,"%.2d%.2d%.3d.%c",m_clsLane.LaneNO(),
			m_clsTime.GetYear()%100,m_clsTime.GetDayCount(),strHead[0]);
		break;
	case MESSAGE_SM:				//汇总消息
//	产生汇总消息的时间按预先定义值(分钟数和秒数总为0)
		sprintf(strMesgHead+MESG_INDEX,"%.4d",		//消息序号
			MesgHeadIndex(nType,nRecordYear%100,nRecordDayCount));
		memmove(strMesgHead+MESG_TYPE,strHead,2);	//消息类型
		sprintf(strMesgHead+MESG_PLAZA,"%.2d",m_clsLane.PlazaNO());
		sprintf(strMesgHead+MESG_YEAR,"%.2d",nRecordYear%100);
		sprintf(strMesgHead+MESG_DAY,"%.3d",nRecordDayCount);
//	由于收费站请求生成SM消息时未指明分钟数和秒数,因此SM的这两项总为0
		sprintf(strMesgHead+MESG_TIME,"%.4d",0);
		sprintf(strMesgHead+MESG_SECOND,"%.2d",0);
//	设定SM消息的备份文件名,扩展名后缀为.s
		sprintf(strBackupName,"%.2d%.2d%.3d.s",m_clsLane.LaneNO(),
			nRecordYear%100,nRecordDayCount);
		break;
	case MESSAGE_MH:				//时报表消息
//	产生时报表的时间按预先定义值
		sprintf(strMesgHead+MESG_INDEX,"%.4d",		//消息序号
			MesgHeadIndex(nType,nRecordYear%100,nRecordDayCount));
		memmove(strMesgHead+MESG_TYPE,strHead,2);	//消息类型
		sprintf(strMesgHead+MESG_PLAZA,"%.2d",m_clsLane.PlazaNO());
		sprintf(strMesgHead+MESG_YEAR,"%.2d",nRecordYear%100);
		sprintf(strMesgHead+MESG_DAY,"%.3d",nRecordDayCount);
		sprintf(strMesgHead+MESG_TIME,"%.2d",nRecordHour);
		sprintf(strMesgHead+MESG_TIME+2,"%.2d",0);
		sprintf(strMesgHead+MESG_SECOND,"%.2d",nRecordSecond);
//	设定MH消息的备份文件名,扩展名后缀为.h
		sprintf(strBackupName,"%.2d%.2d%.3d.h",m_clsLane.LaneNO(),
			nRecordYear%100,nRecordDayCount);
		break;
	}
	sprintf(strMesgHead+MESG_SHIFT_NO,"%c",m_clsStat.ShiftNO());
	sprintf(strMesgHead+MESG_LANE_NO,"%.2d",m_clsLane.LaneNO());
	sprintf(strMesgHead+MESG_COLLECTOR,"%.5u",m_clsStat.CollectNO());
}

//	存储数据到文件
void CRecord::SaveData(UINT nType,char *pStr,UINT nLen)
{
	try{
		char strFileName[80];
		memset(strFileName,0,80);
		sprintf(strFileName,"%s\\%s",INFO_PATH,strBackupName);
		char pBuff[MAX_DATA_LENGTH];
		memset(pBuff,0,MAX_DATA_LENGTH);
		theApp.Encrypt(strMesgHead,pBuff,MESG_HEAD_LENGTH);
		theApp.Encrypt(pStr,pBuff+MESG_HEAD_LENGTH,nLen);	//数据加密

//	在车道控制机硬盘上保存消息备份
		FILE *fp1;
		if((fp1=fopen(strFileName,"a"))==NULL){
			SendMessage(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"存储消息备份失败\n");
		} else {
			fwrite(pBuff,MESG_HEAD_LENGTH+nLen,1,fp1);
			fputc('\n',fp1);
			fclose(fp1);
		}
//	将消息存储到文件中准备上传
		CLaneInfo m_clsLane;
		if(m_clsLane.RAM_Disk()){
			fp1=fopen(TRANS,"a");
		} else {
			fp1=fopen(TRANS_1,"a");
		}
		if(fp1==NULL){
			SendMessage(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"追加TRANS文件失败\n");
			return;
		}
		fwrite(strMesgHead,MESG_HEAD_LENGTH,1,fp1);
		fwrite(pStr,nLen,1,fp1);
		fputc('\n',fp1);
//	获取要发送的消息总长度
		unsigned long nLength=ftell(fp1);
		fclose(fp1);
//	更新消息发送指针文件
		if(m_clsLane.RAM_Disk()){
			AdjustFilePointer(VIDAGE_INF,nLength);
		} else {
			AdjustFilePointer(VIDAGE_INF_1,nLength);
		}
	}
	catch(...){
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CStore::SaveData()出现异常\n");
	}
}

//	调整文件发送指针。由于以后车道控制机中使用了电子盘,发送指针
//	重新使用文件来保存。该文件共分三行,第一行记录了TRANS文件的总
//	长度,第二行记录了下一条要发送消息的位置,第三行记录了已经发
//	出消息的位置,TRANS总长度在每次追加TRANS文件后改写;发送消息
//	时读出当前消息,下一个发送指针指向读出后的位置,当前发送指针
//	指向发送前的位置。如果上位机通知发送成功,用下一个发送指针代
//	替当前发送指针;若上位机发送失败,重新读取并发送该条消息
void CRecord::AdjustFilePointer(char *IndexFile,unsigned long Length)
{
	try{
		FILE *fp1;
		unsigned long CurrentPoint,NextPoint;
		char tmpStr[12];
		memset(tmpStr,0,12);
		if((fp1=fopen(IndexFile,"r"))==NULL){
			CurrentPoint=0;
			NextPoint=0;
		} else {
			fgets(tmpStr,10,fp1);			//总长度
			memset(tmpStr,0,12);
			fgets(tmpStr,10,fp1);			//下一个要发送的指针
			NextPoint=atol(tmpStr);
			memset(tmpStr,0,12);
			fgets(tmpStr,10,fp1);			//当前要发送的指针
			CurrentPoint=atol(tmpStr);
			fclose(fp1);
		}
		if((fp1=fopen(IndexFile,"w"))!=NULL){
			memset(tmpStr,0,12);
			ltoa(Length,tmpStr,10);
			fprintf(fp1,"%s\n",tmpStr);
			memset(tmpStr,0,12);
			ltoa(NextPoint,tmpStr,10);
			fprintf(fp1,"%s\n",tmpStr);
			memset(tmpStr,0,12);
			ltoa(CurrentPoint,tmpStr,10);
			fprintf(fp1,"%s\n",tmpStr);
			fclose(fp1);
		} else {
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"更新消息指针文件失败\n");
		}
	}
	catch(...){
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CRecord::AdjustFilePointer()出现异常\n");
	}
}

//	检查时间:若位于整点则生成时报表;若位于零点则删除指定日期前的文件
void CRecord::ProcessTime()
{
	static UINT nHasRecordHour=0xffff;
	static ULONG nHasRecordDate=0xffffffff;
	CTimeInfo m_clsTime;
//	若位于整点且本小时尚未记录过,生成时报表文件。
//	特别地:每天零点生成的MH时间为上一天的0点
	ULONG nNowDate=(m_clsTime.GetYear()%100)*1000+m_clsTime.GetDayCount();
	if((m_clsTime.GetMinute()==0)&&((nNowDate!=nHasRecordDate)||(m_clsTime.GetHour()!=nHasRecordHour))){
		if(m_clsTime.GetHour()==0){			//若是每天开始
//	将当前UNIX时间减去一整天,即为昨天的时间
			long nLastTime=(long)m_clsTime.GetUnixTime()-24*60*60L;
			struct tm *pLastTime;
			pLastTime=localtime(&nLastTime);
			nRecordYear=pLastTime->tm_year+1900;
			nRecordMonth=pLastTime->tm_mon+1;
			nRecordDay=pLastTime->tm_mday;
			nRecordDayCount=pLastTime->tm_yday+1;
//	特别地:小时消息的生成时间总为整点
			nRecordHour=23;
			nRecordMinute=0;
			nRecordSecond=0;
//	特别地:每天零点生成上一天的MH消息,生成MH消息的时间为零点,收
//			费站收到生成时间为零点的MH消息后自动将其转换为24点			
			RecordMH();
			CStatInfo m_clsStat;
			m_clsStat.ClearMh();
//	以下删除规定日期以前的备份文件,要删除的文件包括车道信息文件、
//	消息序号文件、运行日志文件及抓拍的车辆图像文件
			CLaneInfo m_clsLane;
			UINT nLastYear,nLastDayCount;
			if(m_clsTime.GetDayCount()<=m_clsLane.BackupTime()){
				nLastYear=m_clsTime.GetYear()-1;
				if(((nLastYear%4==0)&&(nLastYear%100!=0))||(nLastYear%400==0)){
					nLastYear=m_clsTime.GetDayCount()+366-m_clsLane.BackupTime();
				} else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -