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

📄 deviceclass.cpp

📁 高速公路收费系统车道软件. 功能: 1 检测公路过往车辆 2 收费过程控制和数据采集 3 车辆信息和图片上传服务器.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// DeviceClass.cpp: implementation of the CCxp class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "lane_new.h"
#include "DeviceClass.h"
#include "mmsystem.h"
#include "mmreg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

extern CLane_newApp theApp;
extern char strPrintInfo[PRINT_INFO_LEN];
extern int nPrintLen;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

BOOL CCxp::bNormalFlag=TRUE;

CCxp::CCxp()
{
}

//	初始化外设状态,设置输入外设状态并请求输入外设输入当前的状态
void CCxp::Initial()
{
	m_clsCxp.AmberStatus('0');
	m_clsCxp.AutoRailStatus('F');
	m_clsCxp.IndicationStatus('R');
	m_clsCxp.LeaveStatus('0');
	m_clsCxp.PictureStatus('0');
	m_clsCxp.LeaveNormalFlag(TRUE);		//初始化时检测线圈正常
	m_clsCxp.PictureNormalFlag(TRUE);	//初始化时抓拍线圈正常
	SendCxpData();
	SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,ASK_IO_STATUS_TIMER,0);
}

//	处理交通指示灯状态
void CCxp::DefineIndicationStatus(char status)
{
	m_clsCxp.IndicationStatus(status);
	SendCxpData();
}

//	处理报警灯状态
void CCxp::DefineAmberStatus(char status)
{
	m_clsCxp.AmberStatus(status);
	SendCxpData();
	if(status=='1'){
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,AMBER_LIGHT_TIMER,0);
	}
}

//	处理自动栏杆状态
void CCxp::DefineAutoRailStatus(char status)
{
	m_clsCxp.AutoRailStatus(status);
	SendCxpData();
}

//	检测线圈占用超时,认为检测线圈故障
void CCxp::LeaveLoopTimerOut()
{
	m_clsCxp.LeaveNormalFlag(FALSE);
}

//	抓拍线圈超时,认为抓拍线圈故障
void CCxp::PictureLoopTimerOut()
{
	m_clsCxp.PictureNormalFlag(FALSE);
}

//	报警灯定时器超时,关闭报警灯
void CCxp::AmberTimerOut()
{
	m_clsCxp.AmberStatus('0');
	SendCxpData();
}

//	查询外设状态定时器超时,继续发送查询命令
void CCxp::AskIoStatusTimerOut()
{
	SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,ASK_IO_STATUS_TIMER,0);
	SendCxpData("\nE\r",3);
}

//	处理来自外设的命令,若以字符'E'开始,则该命令解释为输入外设的状
//	态;若以字符'S'开始,则解释为请求输出外设的状态
void CCxp::ProcessInputData(char *InputData)
{	
	switch(InputData[0]){
	case 'E':			//收到CXP的输入设备状态
//	首先判断所收到字节长度是否合法,若不准确,请求CXP重传
		if(strlen(InputData)!=7){
			AskIoStatusTimerOut();
			return;
		}
//	收到输入/输出设备答复后关闭请求状态定时器
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CLOSE_TIMER,ASK_IO_STATUS_TIMER,0);
//	判断输入外设状态是否发生变化,若#1 线圈或#2 线圈状态发生变化,
//	还需要改变线圈图标的状态
		if(InputData[3]=='1')
		{
			InputData[LEAVE_LOOP_DEVICE+1]='0';
			InputData[3]='0';	
		}else{
			InputData[LEAVE_LOOP_DEVICE+1]='1';		
		}
		
		if(InputData[LEAVE_LOOP_DEVICE+1]!=m_clsCxp.LeaveStatus()){
//	以下两句顺序不可颠倒,否则处理控制类访问检测线圈状态时会得到
//	错误的结果
			m_clsCxp.LeaveStatus(InputData[LEAVE_LOOP_DEVICE+1]);
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,LEAVE_LOOP_CHANGE_STATUS,(LPARAM)InputData[LEAVE_LOOP_DEVICE+1]);
//	检测线圈状态变化,说明检测线圈恢复正常工作
			m_clsCxp.LeaveNormalFlag(TRUE);
			if(InputData[LEAVE_LOOP_DEVICE+1]=='1'){
//	假如检测线圈状态为1,启动定时器,定时器超时前状态不复位则认为
//	线圈故障
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,LEAVE_LOOP_TIMER,0);
			} else {
//	假如检测线圈状态为0,关闭定时器
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CLOSE_TIMER,LEAVE_LOOP_TIMER,0);
			}
		}
		if(InputData[PICTURE_LOOP_DEVICE+1]!=m_clsCxp.PictureStatus()){
//	以下两句顺序不可颠倒,否则处理控制类访问抓拍线圈状态时会得到
//	错误的结果
			m_clsCxp.PictureStatus(InputData[PICTURE_LOOP_DEVICE+1]);
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,PICTURE_LOOP_CHANGE_STATUS,(LPARAM)InputData[PICTURE_LOOP_DEVICE+1]);
//	抓拍线圈状态变化,说明检测线圈恢复正常工作
			m_clsCxp.PictureNormalFlag(TRUE);
			if(InputData[PICTURE_LOOP_DEVICE+1]=='1'){
//	假如抓拍线圈状态为1,启动定时器,定时器超时前状态不复位则认为
//	线圈故障
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,PICTURE_LOOP_TIMER,0);
			} else {
//	假如抓拍线圈状态为0,关闭定时器
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CLOSE_TIMER,PICTURE_LOOP_TIMER,0);
			}
		}
		if(InputData[SPARE1_INPUT_DEVICE+1]!=m_clsCxp.SpareInput1()){
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,SPARE1_INPUT_DEVICE,(LPARAM)InputData[SPARE1_INPUT_DEVICE+1]);
		}
		if(InputData[SPARE2_INPUT_DEVICE+1]!=m_clsCxp.SpareInput2()){
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,SPARE1_INPUT_DEVICE,(LPARAM)InputData[SPARE1_INPUT_DEVICE+2]);
		}
		if(InputData[SPARE3_INPUT_DEVICE+1]!=m_clsCxp.SpareInput3()){
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,SPARE1_INPUT_DEVICE,(LPARAM)InputData[SPARE1_INPUT_DEVICE+3]);
		}
		if(InputData[SPARE4_INPUT_DEVICE+1]!=m_clsCxp.SpareInput4()){
			SendMessage(theApp.m_pMainWnd->m_hWnd,WM_CXP_STATUS,SPARE1_INPUT_DEVICE,(LPARAM)InputData[SPARE1_INPUT_DEVICE+4]);
		}
		break;
	case 'S':					//CXP请求下发输出设备状态
		SendCxpData();
		break;
	default:					//CXP上传的命令不认识
		AskIoStatusTimerOut();	//重新读取CXP状态
		break;
	}
}

//	测试输出设备:将指定的输出设备状态发送到外设
void CCxp::TestOutputDevice(char *pStr)
{
	char tmpStr[20];
	memset(tmpStr,0,20);
	tmpStr[0]=0xa;
	tmpStr[1]='S';
	memmove(tmpStr+2,pStr,12);
	tmpStr[14]=0xd;
	SendCxpData(tmpStr,15);
}

//	通过多串口卡发送外设状态
void CCxp::SendCxpData(char *str1, int Len)
{
	try{
		if(sio_write(CXP_PORT,str1,Len)<Len){
			if(bNormalFlag){
				bNormalFlag=FALSE;
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"向外设板发送数据失败\n");
			}
		} else {
			bNormalFlag=TRUE;
		}
	}
	catch(...){
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CCxp::SendCxpData()出现异常\n");
	}
}

//	封装输出外设状态数据并发送
void CCxp::SendCxpData()
{
	char tmpStr[20];
	memset(tmpStr,0,20);
	tmpStr[0]=0xa;
	tmpStr[1]='S';
	memset(tmpStr+2,'0',12);
	if(m_clsCxp.IndicationStatus()=='R'){
		tmpStr[2+INDICATION_GREEN]='0';
		tmpStr[2+INDICATION_RED]='1';
	} else {
		tmpStr[2+INDICATION_GREEN]='1';
		tmpStr[2+INDICATION_RED]='0';
	}
	if(m_clsCxp.AutoRailStatus()=='F'){
		tmpStr[2+AUTO_RAIL_OPEN]='0';
		tmpStr[2+AUTO_RAIL_CLOSE]='0';
		tmpStr[2+AMBER_DEVICE]=m_clsCxp.AmberStatus();
		tmpStr[14]=0xd;
		SendCxpData(tmpStr,15);
		Sleep(100);
		tmpStr[2+AUTO_RAIL_OPEN]='0';
		tmpStr[2+AUTO_RAIL_CLOSE]='1';
	} else {
		tmpStr[2+AUTO_RAIL_OPEN]='1';
		tmpStr[2+AUTO_RAIL_CLOSE]='0';
	}
	tmpStr[2+AMBER_DEVICE]=m_clsCxp.AmberStatus();
	tmpStr[14]=0xd;
	SendCxpData(tmpStr,15);
}

BOOL CTfi::bAutoTestFlag=FALSE;
BOOL CTfi::bNormalFlag=TRUE;

CTfi::CTfi()
{
}

//	初始化操作:关闭TFI显示
void CTfi::Initial()
{
	ClearTFI();
}

//	清除TFI的显示
void CTfi::ClearTFI()
{
	char tmpStr[10];
	memset(tmpStr,0,10);	
	tmpStr[0]=0x55;
	tmpStr[1]=0xAA;
	tmpStr[2]=0x02;
	tmpStr[3]=0x15;
	tmpStr[4]=0xd;

	SendTFIData(tmpStr,5);
	bAutoTestFlag=FALSE;
}

//	驱动TFI显示车型及金额
void CTfi::DisplayTFI()
{
	char tmpStr[20];
	memset(tmpStr,0,20);
	tmpStr[0]=0x55;
	tmpStr[1]=0xAA;
	tmpStr[2]=0x02;
	tmpStr[3]=0x50;

	CTransInfo m_clsTrans;
	tmpStr[4]=m_clsTrans.BusClass();

	memmove(tmpStr+5,"类 ",3);

	sprintf(tmpStr+8,"%.4d",m_clsTrans.Fare());
	memmove(tmpStr+12,"元",2);
	tmpStr[14]=0xd;
	bAutoTestFlag=FALSE;
	
	SendTFIData(tmpStr,15);
	
	//SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,TFI_TIMER,0);
}

//	音量调节:假设缺省音量为8,每调用本函数一次,音量++或--
void CTfi::AdjustVolume(UCHAR nDirect)
{
	char tmpStr[6];
	memset(tmpStr,0,6);
	tmpStr[0]=0xa;
	tmpStr[1]=0x43;
	if(nDirect==VOLUME_INC){
		tmpStr[2]=0x31;
	} else {
		tmpStr[2]=0x30;
	}
	tmpStr[4]=0xd;
	SendTFIData(tmpStr,4);
	bAutoTestFlag=FALSE;
}

//	通知TFI当前为白天
void CTfi::ShowDay()
{
	char tmpStr[4];
	memset(tmpStr,0,4);
	tmpStr[0]=0xa;
	tmpStr[1]=0x4a;
	tmpStr[2]=0xd;
	SendTFIData(tmpStr,3);
}

//	通知TFI当前为晚上
void CTfi::ShowNight()
{
	char tmpStr[4];
	memset(tmpStr,0,4);
	tmpStr[0]=0xa;
	tmpStr[1]=0x4b;
	tmpStr[2]=0xd;
	SendTFIData(tmpStr,3);
}

//	自动测试TFI:开始自动测试时调用本函数
void CTfi::AutoTestTfi()
{
	bAutoTestFlag=TRUE;
	ProcessTimerOut();
}

//	TFI定时器超时程序:用于自动测试TFI时
void CTfi::ProcessTimerOut()
{
	if(bAutoTestFlag){
//	自动测试时循环显示数字0 - 9,定时器每超时一次,显示数字加1
		static char nValue=0;
		char tmpStr[14];
		memset(tmpStr,0,14);
		tmpStr[0]=0xa;
		tmpStr[1]=0x46;
		for(int i=2;i<11;i++){
			tmpStr[i]=nValue;
		}
		tmpStr[11]=0xd;
		SendTFIData(tmpStr,12);
		if(nValue>=10){
			nValue=0;
		} else {
			nValue++;
		}
		//SendMessage(theApp.m_pMainWnd->m_hWnd,WM_STARTUP_TIMER,TFI_TIMER,0);
	} else {
//	非自动测试时定时器超时,关闭TFI显示
		ClearTFI();
	}


}


//	通过多串口卡发送TFI数据
void CTfi::SendTFIData(char *param1,int length)
{
	CLaneInfo m_clsLane;	
	try{
		if(sio_write(TFI_PORT,param1,length)<length){
			if(bNormalFlag){
				bNormalFlag=FALSE;
				SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"向TFI传送数据失败\n");
			}
		} else {
			bNormalFlag=TRUE;
		}
	}
	catch(...){
		SendMessage(theApp.m_pMainWnd->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CTfi::SendTFIData()出现异常\n");
	}
}

char * CSound::pSoundImage=NULL;		//存储合成后的声音文件
char * CSound::pClass=NULL;			//车型
UINT CSound::nClass=0;
char * CSound::pRMB=NULL;			//圆
UINT CSound::nRMB=0;
char * CSound::pNumber[14];		//数字
UINT CSound::nNumber[14];
char * CSound::pThankYou=NULL;		//祝您一路顺风
char * CSound::pFree=NULL;			//免费
UINT CSound::nFree=0;
char * CSound::pSpace=NULL;
UINT CSound::nSpace=0;
CSound::CSound()
{
}

//	声音初始化:将所有声音文件都由磁盘读入内存
//	声音文件存在于车道软件的安装路径下,本函数首先获取车道软件
//	的安装路径,然后合成声音文件的绝对路径
void CSound::Initial()
{
	char pFullPath[130],pDir[130];
	memset(pFullPath,0,130);
	theApp.GetFullPath(pFullPath);
	int nDirLen=strlen(pFullPath);
	memset(pDir,0,130);
	memmove(pDir,pFullPath,nDirLen);
//	车型声音文件名称为CLASS.WAV
	strcat(pFullPath,"CLASS.WAV");
	nClass=GetSoundLen(pFullPath);
	if(nClass!=0){
		if((pClass=new char[nClass])!=NULL){
			if(!LoadSound(pFullPath,pClass,nClass)){
				delete [] pClass;
				pClass=NULL;
				nClass=0;
			}
		}
	}
//	“圆”声音文件名称为RMB.WAV
	memset(pFullPath,0,130);
	sprintf(pFullPath,"%sRMB.WAV",pDir);
	nRMB=GetSoundLen(pFullPath);
	if(nRMB!=0){
		if((pRMB=new char[nRMB])!=NULL){
			if(!LoadSound(pFullPath,pRMB,nRMB)){
				delete [] pRMB;
				pRMB=NULL;
				nRMB=0;
			}
		}
	}
//	数字声音文件名称必须为x.WAV,其中“百”、“千”、“两”的声音文
//	件名称分别为11.WAV、12.WAV、13.WAV
	for(int i=0;i<14;i++){
		memset(pFullPath,0,130);
		sprintf(pFullPath,"%s%d.WAV",pDir,i);
		nNumber[i]=GetSoundLen(pFullPath);
		if(nNumber[i]!=0){
			if((pNumber[i]=new char[nNumber[i]])!=NULL){
				if(!LoadSound(pFullPath,pNumber[i],nNumber[i])){
					delete [] pNumber[i];
					pNumber[i]=NULL;
					nNumber[i]=0;
					continue;
				}
			}
		}
	}
//	读取“一路顺风”声音文件,该文件名称必须为THANKYOU.WAV
	memset(pFullPath,0,130);
	sprintf(pFullPath,"%sTHANKYOU.WAV",pDir);
	i=GetSoundLen(pFullPath);
	if(i!=0){
		if((pThankYou=new char[i])!=NULL){
			if(!LoadSound(pFullPath,pThankYou,i)){
				delete [] pThankYou;
				pThankYou=NULL;
			}
		}
	}
//	读取“免费”声音文件,该文件名称必须为FREE.WAV
	memset(pFullPath,0,130);
	sprintf(pFullPath,"%sFREE.WAV",pDir);
	nFree=GetSoundLen(pFullPath);
	if(nFree!=0){
		if((pFree=new char[nFree])!=NULL){
			if(!LoadSound(pFullPath,pFree,nFree)){
				delete [] pFree;
				pFree=NULL;
				nFree=0;
			}
		}
	}
//	读取声音间隔文件,该文件名称为SPACE.WAV
	memset(pFullPath,0,130);
	sprintf(pFullPath,"%sSPACE.WAV",pDir);
	nSpace=GetSoundLen(pFullPath);
	if(nSpace!=0){
		if((pSpace=new char[nSpace])!=NULL){
			if(!LoadSound(pFullPath,pSpace,nSpace)){
				delete [] pSpace;
				pSpace=NULL;
				nSpace=0;
			}
		}
	}
}

//	播放语音价格
void CSound::PlayFare()
{
//	首先计算要合成声音的长度,根据该长度分配内存
	UINT nSoundLen;				//存储要播放的数据长度
	nSoundLen=nClass;			//“车型”声音文件
	CTransInfo m_clsTrans;
	int nBusClass=m_clsTrans.BusClass()-'0';
	if(nBusClass<0) nBusClass=0;
	nSoundLen+=nNumber[nBusClass];	//车型数字声音文件
	nSoundLen+=nSpace;				//车型和金额之间增加空格
	int nValue=m_clsTrans.Fare()/1000;
//	获取当前车型声音文件长度
	if(nValue>0){				//累计千位数字声音长度
		nSoundLen+=nNumber[nValue%10];
		nSoundLen+=nNumber[12];	//累计“千”声音长度
	}
	nValue=(m_clsTrans.Fare()%1000)/100;
	if(nValue>0){				//累计百位数字声音长度
		nSoundLen+=nNumber[nValue];
		nSoundLen+=nNumber[11];	//累计“百”声音长度

⌨️ 快捷键说明

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