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