📄 record.cpp
字号:
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 + -