419 lines
14 KiB
C++
419 lines
14 KiB
C++
//---------------------------------------------------------------------------
|
||
#include "stdafx.h"
|
||
//------------------------------------------------------------------------------
|
||
#pragma hdrstop
|
||
|
||
#include <string>
|
||
#include <windows.h>
|
||
|
||
//#include <IniFiles.hpp>
|
||
#include "Validator.h"
|
||
#include "inifile.h"
|
||
#include "stdTools.h"
|
||
//#include "ud_Module.h"
|
||
|
||
//---------------------------------------------------------------------------
|
||
//Validator* validator=NULL;
|
||
//---------------------------------------------------------------------------
|
||
//---------------------------------------------------------------------------
|
||
unsigned char ConReset[6] = { 0x02,0x03,0x06,0x30,0x41,0xB3 }; //RESET Ïåðåçàãðóçèòü âàëèäàòîð
|
||
|
||
unsigned char ConReACK[6] = { 0x02,0x03,0x06,0x00,0xC2,0x82 }; //Îòâåò âàëèäàòîðó ÷òî âñ¸ íîðìàëüíî...
|
||
unsigned char ConStPoll[6] = { 0x02,0x03,0x06,0x33,0xDA,0x81 }; //POLL 33H Request for Bill-to-Bill unit activity Status (Ïåðåéòè â ðåæèì ïîëó÷åíèÿ ïëàòåæåé)
|
||
unsigned char ConIdent[6] = { 0x02,0x03,0x06,0x37,0xFE,0xC7 }; //IDENTIFICATION 37H Request for Model, Serial Number, Country ISO code, Asset Number
|
||
|
||
//#pragma package(smart_init)
|
||
//---------------------------------------------------------------------------
|
||
#define POLYNOMIAL 0x08408
|
||
unsigned int GetCRC16(unsigned char* bufData, unsigned int sizeData)
|
||
{
|
||
unsigned int CRC, i;
|
||
unsigned char j;
|
||
CRC = 0;
|
||
for(i=0; i < sizeData; i++)
|
||
{
|
||
CRC ^= bufData[i];
|
||
for(j=0; j < 8; j++)
|
||
{
|
||
if(CRC & 0x0001) {CRC >>= 1; CRC ^= POLYNOMIAL;}
|
||
else CRC >>= 1;
|
||
}
|
||
}
|
||
return CRC;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
/*unsigned int GetCRC16(char* bufData, unsigned int sizeData)
|
||
{ return GetCRC16((unsigned char*)bufData, sizeData);
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
//Äîáàâèòü íóëè ê öèôðå
|
||
int addZero(int val,int cnt)
|
||
{
|
||
for(int i=0;i<cnt;i++)
|
||
val=val*10;
|
||
return val;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
Validator::Validator()
|
||
{
|
||
//Pay=0;
|
||
cPort=new ComPort();
|
||
bNominals=false; //Ïîëó÷èëè õîòü 1 ðàç íîìèíàëû êóïþï
|
||
|
||
pthread_mutex_init(&m_mutex, NULL);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
Validator::~Validator()
|
||
{
|
||
stopPay();
|
||
pthread_mutex_destroy(&m_mutex);
|
||
delete cPort;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Çàãðóçèòü íàñòðîéêè èç ini ôàéëà
|
||
/*void Validator::LoadSetup()
|
||
{
|
||
TIniFile* ini = new TIniFile();
|
||
ini->Load("settings.ini");
|
||
cPort->ComNumber=ini->ReadString("Validator","Port","0");
|
||
cPort->BaudRate=ini->ReadLong("Validator","BaudRate","0");
|
||
m_testmode=ini->ReadBool("Validator","TestMode","0");
|
||
delete ini;
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
bool Validator::OpenCOMPort(std::string ComNumber, int BaudRate)
|
||
{
|
||
cPort->ComNumber = ComNumber;
|
||
cPort->BaudRate = BaudRate;
|
||
|
||
cPort->Close();
|
||
|
||
if (cPort->Open(cPort->ComNumber))
|
||
{
|
||
if (!cPort->Setup(2))
|
||
return false;
|
||
|
||
if (!cPort->SetTimeout(500)) //50 ýòî 5 ñåêóíä òàê êàê çàäà¸òñÿ â 1/10 ñåêóíäû
|
||
return false;
|
||
}
|
||
else return false;
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ñðàâíèòü ïîñëåäíèå 2 áàéòà ñ CRC äàííûõ
|
||
bool Validator::CheckOnCRC(unsigned char* lpBuffer,unsigned long nSize)
|
||
{
|
||
if(nSize<2) return false;
|
||
unsigned int CRC=GetCRC16(lpBuffer,nSize-2);
|
||
unsigned int* pCRC=(unsigned int*)&lpBuffer[nSize-2];
|
||
return (CRC==*pCRC);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//req - Ñòðîêà çàïðîñà áåç CRC
|
||
//ans - Îòâåò íà êîìàíäó
|
||
//Ðåçóëüòàòà ñîâïàë CRC èëè íåò
|
||
bool Validator::SendCommand(std::string req, std::string &ans)
|
||
{
|
||
unsigned short crc=GetCRC16((unsigned char*)req.c_str(),req.size());
|
||
req+=((char*)(&crc))[0]; req+=((char*)(&crc))[1];
|
||
unsigned int BytesWritten=cPort->Write(req.c_str(),req.size());
|
||
//×òåíèå îòâåòà
|
||
ans="";
|
||
for(int i=0;i<255;i++)
|
||
{
|
||
Sleep(10);
|
||
char ch;
|
||
unsigned int BytesRead=cPort->Read(&ch,1);
|
||
if (BytesRead>0) ans+=ch; else break;
|
||
}
|
||
//Ïðîâåðêà îòâåòà íà CRC
|
||
if(ans.size()>=2)
|
||
{
|
||
crc=GetCRC16((unsigned char*)ans.c_str(),ans.size()-2);
|
||
if(crc==((unsigned short*)(&ans.c_str()[ans.size()-2]))[0]) return true;
|
||
}
|
||
return false;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Èíèöèàëèçàöèÿ ïåðåìåííûõ âàëèäàòîðà
|
||
bool Validator::Start()
|
||
{
|
||
bool result=true;
|
||
|
||
if(result) result=result && Reset(); //Ïåðåçàãðóçèòü âàëèäàòîð
|
||
if(result) result=result && getSerialNumber(); //Ïîëó÷èòü ñåðèéíûé íîìåð âàëèäàòîðà
|
||
if(result) result=result && getNominals(); //Ïîëó÷èòü íîìèíàëû ïðîøèòûõ êóïþð
|
||
if(result) result=result && SetEnableBillTypes(true); //Ðàçðåøèòü ïðè¸ì âñåõ ïðîøèòûõ êóïþð
|
||
|
||
return result || m_testmode; // òåñòîâîì ðåæèìå âñåãäà âñ¸ OK
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ïåðåçàãðóçèòü âàëèäàòîð (RESET 30H Command for Bill-to-Bill unit to self-reset)
|
||
bool Validator::Reset()
|
||
{
|
||
std::string req,ans;
|
||
req+=(char)0x02; req+=(char)0x03; req+=(char)0x06; req+=(char)0x30;
|
||
return SendCommand(req,ans);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ïîëó÷èòü ñòàòóñ âàëèäàòîðà (GET STATUS 31H Request for Bill-to-Bill unit set-up status)
|
||
bool Validator::GetStatus()
|
||
{
|
||
std::string req,ans;
|
||
req+=(char)0x02; req+=(char)0x03; req+=(char)0x06; req+=(char)0x31; //req+=(char)0x41; req+=(char)0xB3;
|
||
bool r=SendCommand(req,ans);
|
||
if(r && ans.length()>6) //Ïî÷åìó òî âñåãäà áåç äàííûõ
|
||
{
|
||
//Ïåðâûå 3 áàéòà ïîêàçûâàþò êàêèå òèïû ïëàòèæåé ðàçðåøåíû
|
||
//Ñëåäóþùèå 3 áàéòà óêàçûâàþò êàêîé óðîâåíü çàùèòû óñòàíîâëåí
|
||
//Ñëåäóþùèå 3 Ïî ìîåìó êàêèå êàñåòû ãîòîâû ïðèíèìàòü äåíüãè
|
||
}
|
||
return r;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ðàçðåøèòü ëèáî çàïðåòèòü ïðè¸ì çàäàííûõ âèäîâ êóïþð
|
||
//enable - true ðàçðåøèòü âñ¸, false çàïðåòèòü âñ¸
|
||
bool Validator::SetEnableBillTypes(bool enable)
|
||
{
|
||
std::string req,ans;
|
||
if(enable)
|
||
{ req+=(char)0x02; req+=(char)0x03; req+=(char)0x0C; req+=(char)0x34;
|
||
req+=(char)0xFF; req+=(char)0xFF; req+=(char)0xFF; //24 áèòà
|
||
req+=(char)0x00; req+=(char)0x00; req+=(char)0x00; //24 áèòà
|
||
}else
|
||
{ req+=(char)0x02; req+=(char)0x03; req+=(char)0x0C; req+=(char)0x34;
|
||
req+=(char)0x00; req+=(char)0x00; req+=(char)0x00; //24 áèòà
|
||
req+=(char)0x00; req+=(char)0x00; req+=(char)0x00; //24 áèòà
|
||
}
|
||
bool r=SendCommand(req,ans);
|
||
return r;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool Validator::getSerialNumber()
|
||
{
|
||
unsigned int BytesWritten=cPort->Write(ConIdent,sizeof(ConIdent));
|
||
unsigned int BytesRead=cPort->Read(ReadAr,sizeof(ReadAr));
|
||
if(!CheckOnCRC(ReadAr,BytesRead)) return false;
|
||
//Íóæíûé ëè íàì îòâåò
|
||
if(BytesRead!=39)
|
||
{
|
||
Utility::logrotate("validator.log","Íå óäàëîñü ïîëó÷èòü íîìåð ïàðòèè âàëèäàòîðà");
|
||
return false;
|
||
}
|
||
//Âûáèðàåì ¹ ïàðòèè
|
||
std::string str1((char*)&ReadAr[3],15);
|
||
BatchNumber= Utility::trim(str1);
|
||
|
||
std::string str2((char*)&ReadAr[18],12);
|
||
SerialNumber= Utility::trim(str2);
|
||
|
||
Sleep(100);
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ïîëó÷èòü íîìèíàëûû êóïþð ïðèíèìàåìûå âàëèäàòîðîì
|
||
bool Validator::getNominals()
|
||
{
|
||
unsigned char ConGetBT[6] = { 0x02,0x03,0x06,0x41,0x4F,0xD1 }; //GET BILL TABLE Êàêèå êóïþðû ïðîøèòû â âàëèäàòîðå
|
||
ConGetBT[5] = GetCRC16(ConGetBT, 5); //Ñ÷èòàþ CRC
|
||
|
||
bNominals=false;
|
||
Sleep(100); //íà âñÿê
|
||
unsigned int BytesWritten=cPort->Write(ConGetBT,sizeof(ConGetBT));
|
||
unsigned int BytesRead=cPort->Read(ReadAr,sizeof(ReadAr));
|
||
if(!CheckOnCRC(ReadAr,BytesRead)) return bNominals;
|
||
Sleep(100); //íà âñÿê
|
||
for(unsigned char i=0;i<23;i++)
|
||
{
|
||
bt[i].val=addZero(ReadAr[3+i*5],ReadAr[3+i*5+4]);
|
||
//Êîä ñòðàíû 3 áóêâû
|
||
bt[i].country[0]=ReadAr[3+i*5+1];
|
||
bt[i].country[1]=ReadAr[3+i*5+2];
|
||
bt[i].country[2]=ReadAr[3+i*5+3];
|
||
bt[i].val=addZero(ReadAr[3+i*5],ReadAr[3+i*5+4]);
|
||
}
|
||
bNominals=true;
|
||
return bNominals;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ïîïûòêà ïðè¸ìà ïëàòåæà, âûïîëíÿåòñÿ â öèêëå â îòäåëüíîì ïîòîêå.
|
||
//state - òåêóùåå ñîñòîÿíèå âàëèäàòîðà (Ñì. äîêóìåíòàöèþ)
|
||
//ðåçóëüòàò ïðèíÿòàÿ ñóììà èëè 0 åñëè íè÷åãî íå ïðèíÿòî
|
||
int Validator::getTHPay(int &state)
|
||
{
|
||
state=0;
|
||
int result = 0;
|
||
if(!cPort->isOpen()){Sleep(1000); return result;}
|
||
|
||
unsigned char buffer[255];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
|
||
unsigned int BytesWritten=0;
|
||
unsigned int BytesRead=0;
|
||
|
||
BytesWritten=cPort->Write(ConReACK, sizeof(ConReACK)); //Îòâåò âàëèäàòîðó ÷òî âñ¸ íîðìàëüíî
|
||
Sleep(10);
|
||
|
||
BytesWritten=cPort->Write(ConStPoll, sizeof(ConStPoll)); //Ïåðåéòè â ðåæèì ïîëó÷åíèÿ ïëàòåæåé
|
||
BytesRead=cPort->Read(buffer,sizeof(buffer));
|
||
if(CheckOnCRC(buffer,BytesRead))
|
||
{
|
||
switch (buffer[3])
|
||
{
|
||
case 0x13://19 Åù¸ â ðåæèìå èíèöèàëèçàöèè ïîñëå âûïîëíåíèÿ êîìàíäû RESET
|
||
//Utility::logrotate("validator.log","(State)0x13 Èíèöèàëèçàöèÿ");
|
||
break;
|
||
case 0x14: //20 Îçíà÷àåò ÷òî íàõîäèìñÿ â ðåæèìå îæèäàíèÿ ïðè¸ìà ïëàòåæà (IDLING – The state in which Bill-to-Bill is ready accept bills)
|
||
//Utility::logrotate("validator.log","(State)0x14 Â ðåæèìå îæèäàíèÿ êóïþðû");
|
||
break;
|
||
case 0x15: //21 Ïðîèçâîäèò ñêàíèðîâàíèå êóïþðû è îïðåäåëÿåòñÿ íàìèíàë (Ó ìåíÿ 3 ðàçà íà êóïþðó)
|
||
state = 0x15;
|
||
//Utility::logrotate("validator.log","(State)21 Ïðîøëà 1 èç ïðîâåðîê");
|
||
break;
|
||
case 0x17: //23 Ïðè¸ì êóïþðû â îòñåê åñëè íå ïîëó÷èòñÿ ïîëîæèòü òî âåðí¸ò êóïþðó îáðàòíî
|
||
state = 0x17;
|
||
//Utility::logrotate("validator.log","(State)23 Ïðè¸ì êóïþðû!");
|
||
break;
|
||
case 0x19://25 DISABLED – The Bill-to-Bill unit has been disabled by the Controller and also the state in which Bill-to-Bill unit is after initialization.
|
||
state = 0x19;
|
||
//Utility::logrotate("validator.log","(State)25 îòìåí¸í ïðè¸ì!!!");
|
||
SetEnableBillTypes(true);
|
||
break;
|
||
case 0x1c: //28 Èçâëå÷åíà êóïþðà
|
||
//Utility::logrotate("validator.log","(State)28 Êóïþðà èçâëå÷åíà");
|
||
break;
|
||
case 0x41: //41H Çàïîëíèëñÿ ìåøîê ïîä çàâÿçêó...
|
||
//Utility::logrotate("validator.log","(State)0x41 Çàïîëíèëñÿ ìåøîê ïîä çàâÿçêó...");
|
||
break;
|
||
case 0x45: //69 Îáíàðóæåíà ïîïûòêà îáìàíà "ôàëüøèâêà".
|
||
//Utility::logrotate("validator.log","(State)69 Íåçíàþ");
|
||
break;
|
||
case 0x81: //129 Â êàêóþ êàñåòó ïîïàëà êóïþðà
|
||
state = 0x81;
|
||
//Utility::logrotate("validator.log","(State)129 Ïðèíÿòà êóïþðà");
|
||
if (buffer[4]<23)
|
||
{
|
||
result = bt[buffer[4]].val; //Â êàñåòå buffer[5]
|
||
Utility::logrotate("validator.log", "(Pay)" + Utility::IntToStdStr(result));
|
||
}
|
||
break;
|
||
default:
|
||
Utility::logrotate("validator.log", "(State???)" + Utility::IntToStdStr(buffer[3]));
|
||
}
|
||
|
||
Utility::logrotate("validator.log", "buffer[3] = " + Utility::IntToStdStr(buffer[3]));
|
||
Utility::logrotate("validator.log", "state = " + Utility::IntToStdStr(state));
|
||
|
||
}
|
||
Sleep(100);
|
||
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Çàâåðøåíèå ðàáîòû ïî ïðè¸ìó ïëàòåæåé
|
||
void Validator::endPay()
|
||
{
|
||
SetEnableBillTypes(false);
|
||
|
||
unsigned int BytesWritten,BytesRead;
|
||
BytesWritten=cPort->Write(ConReACK , sizeof(ConReACK));
|
||
|
||
BytesWritten=cPort->Write(ConStPoll , sizeof(ConStPoll));
|
||
BytesRead=cPort->Read(ReadAr,sizeof(ReadAr));
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
int Validator::GetState() //Åñëè 0 òî âñ¸ â ïîðÿäêå
|
||
{
|
||
if(m_testmode) return 0;
|
||
//if(! bNominals) getNominals(); //todo íå ïîäõîäèò äëÿ ïðîâåðêè
|
||
if(! bNominals) return 1;
|
||
return 0;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string Validator::GetStatusDescription(char StatusCode) //Îïèñàíèå ñòàòóñà
|
||
{
|
||
if (StatusCode == 0x00)
|
||
return "OK";
|
||
else
|
||
if (StatusCode == 1)
|
||
return "Íå óäàëîñü ïîëó÷èòü íîìèíàëû êóïþð";
|
||
else
|
||
return "Error";
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool Validator::startPay() //Ñòàðòóåì ïîòîê
|
||
{
|
||
if (!execute_thread) //×òîáû íå çàïóñêàòü ïîòîê çàíîâî
|
||
{
|
||
int ret = pthread_create(&m_threadid, NULL, Validator::thread_func, (void*)this);
|
||
if (ret == 0)
|
||
execute_thread = true;
|
||
}
|
||
return execute_thread;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool Validator::stopPay() //Ñòîïèì ïîòîê ñ îæèäàíèåì åãî çàâåðøåíèÿ
|
||
{
|
||
if (execute_thread)
|
||
{
|
||
execute_thread = false;
|
||
void* ret = NULL;
|
||
pthread_join(m_threadid, &ret);
|
||
}
|
||
return !execute_thread;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
void* Validator::thread_func(void *pData)
|
||
{
|
||
Validator* validator=(Validator*) pData;
|
||
while (validator->execute_thread)
|
||
{
|
||
int pay,state;
|
||
pay = validator->getTHPay(state);
|
||
//Çàùèùàåì ïåðåìåííóþ ìþòåêñîì
|
||
if (pthread_mutex_lock(&validator->m_mutex) == 0)
|
||
{
|
||
validator->m_payState = state;
|
||
pthread_mutex_unlock(&validator->m_mutex);
|
||
}
|
||
if (pay > 0) //Åñëè ïðîèçâåëè îïëàòó òî äîáàâëÿåì â ñïèñîê ïëàòåæåé
|
||
{
|
||
if (pthread_mutex_lock(&validator->m_mutex) == 0) //Çàùèùàåì ñïèñîê ìþòåêñîì
|
||
{
|
||
validator->m_pays.add(pay);
|
||
pthread_mutex_unlock(&validator->m_mutex);
|
||
}
|
||
}
|
||
}
|
||
validator->endPay();
|
||
return NULL;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Ïîëó÷èòü çíà÷åíèå èç íîêîïèâøåãîñÿ ñïèñêà îïëàò, çíà÷åíèå óäàëÿåòñÿ èç ñïèñêà
|
||
//Åñëè ÷òî çàïëàòèëè òî ðåçóëüòàò áîëüøå íóëÿ
|
||
int Validator::getPay()
|
||
{
|
||
int pay = 0;
|
||
if (pthread_mutex_lock(&m_mutex) == 0) //Çàùèùàåì ñïèñîê ìþòåêñîì
|
||
{
|
||
if (m_pays.count() > 0)
|
||
{
|
||
pay = m_pays.get(0);
|
||
m_pays.del((unsigned int)0);
|
||
}
|
||
pthread_mutex_unlock(&m_mutex);
|
||
}
|
||
return pay;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
int Validator::getPayState()
|
||
{
|
||
int result = 0;
|
||
if (pthread_mutex_lock(&m_mutex) == 0) //Çàùèùàåì ñïèñîê ìþòåêñîì
|
||
{
|
||
result = m_payState;
|
||
pthread_mutex_unlock(&m_mutex);
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|