Files
Tools_CPP/devices/Validators/Validator.cpp
2024-11-01 12:23:13 +05:00

419 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//---------------------------------------------------------------------------
#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;
}
//---------------------------------------------------------------------------