CAP/cap_gestion/crd_ctrl.cpp
2021-09-01 18:53:06 +02:00

464 lines
14 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#include <mmsystem.h>
#include <inifiles.hpp>
#include "stdio.h"
#pragma hdrstop
#include "crd_ctrl.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TCardCtrl *CardCtrl;
//---------------------------------------------------------------------------
__fastcall TCardCtrl::TCardCtrl(TComponent* Owner)
: TForm(Owner)
{
LM_opened = false;
char COMM[][10] = { "COM1", "COM2", "COM3", "COM4" };
IDcard = 0;
TbCards->Active = true;
Height = 270;
// Recuperamos la configuración
TIniFile *ini;
ini = new TIniFile( ExtractFileDir( Application->ExeName ) + "\\CAP.INI" );
// General
PuertoE = ini->ReadInteger( "CAP_w", "PuertoEscritor", 1 );
AbrePuerto( COMM[PuertoE]);
cb_PosP = ini->ReadInteger( "CAP_w", "PosPrefijo", 0 );
cb_LenP = ini->ReadInteger( "CAP_w", "LenPrefijo", 2 );
cb_PosC = ini->ReadInteger( "CAP_w", "PosCodigo", 2 );
cb_LenC = ini->ReadInteger( "CAP_w", "LenCodigo", 8 );
cb_PosR = ini->ReadInteger( "CAP_w", "PosRevision", 10 );
cb_LenR = ini->ReadInteger( "CAP_w", "LenRevision", 2 );
cb_PosFd = ini->ReadInteger( "CAP_w", "PosFechaDesde", 12 );
cb_PosFh = ini->ReadInteger( "CAP_w", "PosFechaHasta", 18 );
delete ini;
}
//---------------------------------------------------------------------------
int __fastcall TCardCtrl::LocateCard( int idc, int owner )
{
int dev = idc; int version = 0;
if ( !TbCards->Locate( "id", idc, TLocateOptions() << loCaseInsensitive << loPartialKey ) )
{
Height = 270;
noCardFound->Visible = true;
TbCards->Insert();
TbCards->FieldByName("idowner")->AsInteger = owner;
TbCards->FieldByName("idCard")->AsInteger = 0+((version&0x1F)<<1)+(owner<<6);
TbCards->FieldByName("vCard")->AsInteger = version;
TbCards->Post();
dev = TbCards->FieldByName( "id" )->AsInteger;
}
return dev;
}
//---------------------------------------------------------------------------
void __fastcall TCardCtrl::BitBtn2Click(TObject *Sender)
{
if ( TbCards->FieldByName("idCard")->AsInteger & 0x0001 )
{
ShowMessage( "La tarjeta pertenece a un ABONADO TEMPORAL, por lo que su version no puede ser incrementada");
} else {
int newVersion, idCard;
if ( Application->MessageBox("Reasignación código tarjeta, inutilizará la tarjeta actual. ¿Realmente desea continuar?", "CRD: cambio de tarjetra", MB_OKCANCEL) != IDOK)
return;
newVersion = (TbCards->FieldByName("vCard")->AsInteger+1)%32;
idCard = TbCards->FieldByName("idCard")->AsInteger;
TbCards->Edit();
TbCards->FieldByName("vCard")->AsInteger = newVersion;
TbCards->FieldByName("idCard")->AsInteger = (idCard & 0xFFC1) + ((newVersion&0x1F)<<1);
TbCards->Post();
}
}
//---------------------------------------------------------------------------
//----------------------- ESCRITOR DE TARJETAS ------------------------------
int __fastcall TCardCtrl::AbrePuerto(LPTSTR lpszPortName)
{
DWORD dwError;
DCB PortDCB;
COMMTIMEOUTS CommTimeouts;
if ( LM_opened ) return true;
LM_opened = false;
// Open the serial port.
LM_handle = CreateFile (lpszPortName, // Pointer to the name of the port
GENERIC_READ | GENERIC_WRITE,
// Access (read/write) mode
0, // Share mode
NULL, // Pointer to the security attribute
OPEN_EXISTING,// How to open the serial port
0, // Port attributes
NULL); // Handle to port with attribute
// to copy
// If it fails to open the port, return FALSE.
if ( LM_handle == INVALID_HANDLE_VALUE )
{
dwError = GetLastError ();
return false;
} else {
LM_opened = true;
}
PortDCB.DCBlength = sizeof (DCB);
// Get the default port setting information.
GetCommState (LM_handle, &PortDCB);
// Change the DCB structure settings.
PortDCB.BaudRate = 9600; // Current baud
PortDCB.fBinary = TRUE; // Binary mode; no EOF check
PortDCB.fParity = TRUE; // Enable parity checking.
PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control
PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;
// DTR flow control type
PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx
PortDCB.fOutX = FALSE; // No XON/XOFF out flow control
PortDCB.fInX = FALSE; // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE; // Disable error replacement.
PortDCB.fNull = FALSE; // Disable null stripping.
PortDCB.fRtsControl = RTS_CONTROL_ENABLE;
// RTS flow control
PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on
// error.
PortDCB.ByteSize = 7; // Number of bits/bytes, 4-8
/*
PortDCB.ByteSize = 8; // Number of bits/bytes, 4-8
*/
PortDCB.Parity = EVENPARITY; // 0-4=no,odd,even,mark,space
PortDCB.StopBits = 0; // 0,1,2 = 1, 1.5, 2
// Configure the port according to the specifications of the DCB
// structure.
if (!SetCommState (LM_handle, &PortDCB))
{
// Could not configure the serial port.
///*-*/ printf( "Unable to configure the serial port\n%s\n" );
dwError = GetLastError ();
return FALSE;
}
// Retrieve the time-out parameters for all read and write operations
// on the port.
GetCommTimeouts (LM_handle, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
// CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
CommTimeouts.ReadTotalTimeoutConstant = 1000;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
// Set the time-out parameters for all read and write operations
// on the port.
if (!SetCommTimeouts (LM_handle, &CommTimeouts))
{
// Could not set the time-out parameters.
///*-*/ printf( "Unable to set the time-out parameters" );
dwError = GetLastError ();
return FALSE;
}
// Direct the port to perform extended functions SETDTR and SETRTS.
// SETDTR: Sends the DTR (data-terminal-ready) signal.
// SETRTS: Sends the RTS (request-to-send) signal.
EscapeCommFunction (LM_handle, SETDTR);
EscapeCommFunction (LM_handle, SETRTS);
return LM_opened;
};
void __fastcall TCardCtrl::CierraPuerto(void)
{
if ( LM_opened )
{
CloseHandle( LM_handle );
}
};
// ObtenerRespuesta
// Lee del puerto los datos pendientes del buffer
// (solo lee lo que expulse el LM)
//
//
char * __fastcall TCardCtrl::ObtenerRespuesta( char *rcv )
{
bool waitingResp = true;
DWORD CHK, chkF = 0;
int i = 0;
DWORD dwCommModemStatus;
if ( LM_opened )
{
/*
// Specify a set of events to be monitored for the port.
SetCommMask (LM_handle, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
// Wait for an event to occur for the port.
WaitCommEvent (LM_handle, &dwCommModemStatus, 0);
// Re-specify the set of events to be monitored for the port.
SetCommMask (LM_handle, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING);
*/
// Recogemos la respuesta del lector
while( i < 75 )
{
ReadFile( LM_handle, &(rcv[i]), 1, &CHK, NULL );
if ( CHK == 1 )
{
if ( waitingResp )
{
if ( rcv[i] != 0x06) waitingResp = false;
// ACK
// printf( "Esperando a la tarjeta\n" );
}
if ( rcv[i] == 13 ) break; else {
if ( !waitingResp || i==0 ) i++;
}
} else
if ( CHK == 0 )
{
chkF++;
if ( chkF == 20 )
{
sprintf( rcv, "ERROR: Respuesta fuera de tiempo" );
return rcv;
}
}
}
rcv[i+1] = '\0';
} else {
sprintf( rcv, "ERROR: LM no abierto" );
}
#ifdef _verbose
///*-*/ printf( "Recibido: %s\n", rcv );
#endif
return rcv;
};
// EnviarComando
// Envia el comando CMD al lector ID, devolviendo la respuesta 'rcv'
//
//
//
char * __fastcall TCardCtrl::EnviaCMD1( char *CMD, char *rcv, char mlen )
{
DWORD CHK;
if ( LM_opened )
{
#ifdef _verbose
///*-*/ printf( "Enviado: %s\n", CMD );
#endif
WriteFile( LM_handle, CMD, strlen(CMD)+mlen, &CHK, NULL );
ObtenerRespuesta( rcv );
} else
sprintf( rcv, "ERROR: LM no abierto" );
return rcv;
}
char * __fastcall TCardCtrl::EnviaCMD( char *CMD, char *rcv )
{
EnviaCMD1( CMD, rcv, 0 );
return rcv;
}
#define ZT_ClearCommand "/CL0/"
// #define ZT_ReadCommand "/RD3/"
#define ZT_ReadCommand "/RD1/"
#define ZT_WriteCommand "/WR1/"
#define ACK 0x06
#define STX 0x02
#define NAK 0x15
#define ETX 0x03
#define EOT 0x04
#define CR 0x0D
char __fastcall TCardCtrl::CalculaBCC( char *cadena )
{
int i, dev=0;
for ( i=0; cadena[i] != ETX; i++ )
{
dev ^= cadena[i];
}
dev ^= cadena[i];
return dev;
}
char * __fastcall TCardCtrl::LeeTarjeta( char *rcv )
{
// Leemos una tarjeta
char buff[3], buff2[80];
EnviaCMD( ZT_ReadCommand, rcv );
if ( rcv[0] == ACK && rcv[1] == 0x0D )
{
// Ahora si se ha recibido <ACK><CR> Leemos la tarjeta que pasemos
sndPlaySound("snd\\inserta_card_leer.wav", SND_ASYNC | SND_FILENAME);
ObtenerRespuesta( rcv );
// Vemos si es la tarjeta o un error
if ( rcv[0] == STX && rcv[1] == '/' && rcv[2] == 'E' && rcv[3] == 'R' )
{
//es un error
#ifdef _verbose
///*-*/ printf( "Error: %d", rcv[1] );
#endif
} else {
char len = 0;
while( rcv[len]!=CR )len++;
char BCC = CalculaBCC( &rcv[1] ),
BCCr = rcv[ len-1 ];
if ( BCC != BCCr )
{
sprintf( rcv, "Error: BCC recibido es incorrecto BCC(%x) != R(%x)\n", BCC, BCCr );
}
}
buff[0] = ACK; buff[1] = '\0';
EnviaCMD( buff, buff2 );
} else {
sprintf( rcv, "ERROR: Commando no aceptado\n");
}
return rcv;
}
char * __fastcall TCardCtrl::EscribeTarjeta( char *datos, char *rcv )
{
// Leemos una tarjeta
char env[140], buff[140], BCC;
EnviaCMD( ZT_WriteCommand, rcv );
if ( rcv[0] == ACK && rcv[1] == CR )
{
sprintf( env, "%s%c", datos, ETX );
BCC = CalculaBCC( env );
sprintf( buff, "%c%s%c", STX, env, BCC );
if ( BCC )
EnviaCMD( buff, rcv );
else
EnviaCMD1( buff, rcv, 1 );
if ( rcv[0] == ACK && rcv[1] == CR )
{
// Ahora si se ha recibido <ACK><CR> Leemos la tarjeta que pasemos
sndPlaySound("snd\\inserta_card_grabar.wav", SND_ASYNC | SND_FILENAME);
ObtenerRespuesta( rcv );
// Vemos si es la tarjeta o un error
if ( !(rcv[0] == EOT && rcv[1] == CR) )
{
//es un error
sprintf( rcv, "Error: %s\n", rcv );
#ifdef _verbose
///*-*/ printf( "Error: %s\n", rcv );
#endif
}
buff[0] = ACK; buff[1] = CR; buff[2] = '\0';
EnviaCMD( buff, rcv );
} else {
sprintf( rcv, "ERROR: No se recibio respuesta despues de los datos\n" );
}
} else {
sprintf( rcv, "ERROR: Commando no aceptado\n");
}
return rcv;
}
void __fastcall TCardCtrl::GrabaTarjeraClick(TObject *Sender)
{
char rcv[140];
statusOK = false;
if ( LM_opened )
{
// Inicializamos el ZT-2300
EnviaCMD( ZT_ClearCommand, rcv );
if ( rcv[0] == 'E' )
{
ShowMessage( "Error inicializando el GRABADOR" );
} else {
char rcv[80], card[140];
ObtenCadenaTarjeta(card);
EscribeTarjeta( card, rcv );
statusOK = !( rcv[0] == 'E' && rcv[5] == ':' );
}
} else {
ShowMessage("El Puerto no pudo ser ABIERTO" );
}
}
//---------------------------------------------------------------------------
char * __fastcall TCardCtrl::ObtenCadenaTarjeta(char *dev)
{
int Prefijo = 20, Rev = 0;
//-----
if ( IDcard != 0 )
sprintf( dev, "%02d%08d%02d", Prefijo, IDcard, Rev );
else
sprintf( dev, "%02d%08d%02d", Prefijo, TbCards->FieldByName("idCard")->AsInteger, Rev );
return dev;
}
void __fastcall TCardCtrl::VerificarTarjetaClick(TObject *Sender)
{
char rcv[140];
if ( LM_opened )
{
// Inicializamos el ZT-2300
EnviaCMD( ZT_ClearCommand, rcv );
if ( rcv[0] == 'E' )
{
ShowMessage( AnsiString( rcv ) + "Error inicializando el GRABADOR" );
} else {
char rcv[80], buff[80], card[140];
ObtenCadenaTarjeta(card);
LeeTarjeta( rcv ); int i;
for( i=1; rcv[i] != ETX; i++ ) buff[i-1]=rcv[i];
buff[i-1]='\0';
if ( strcmp( buff, card ) != 0 )
{
sndPlaySound("snd\\card_verify_error.wav", SND_ASYNC | SND_FILENAME);
ShowMessage("La tarjeta pasada, no se corresponde");
} else {
sndPlaySound("snd\\card_verify_ok.wav", SND_ASYNC | SND_FILENAME);
ShowMessage("La tarjeta pasada, es correcta");
}
}
} else {
ShowMessage("El Puerto no pudo ser ABIERTO" );
}
}
//---------------------------------------------------------------------------
void __fastcall TCardCtrl::FormClose(TObject *Sender, TCloseAction &Action)
{
if ( LM_opened ) CierraPuerto();
}
//---------------------------------------------------------------------------