1010 lines
30 KiB
C++
1010 lines
30 KiB
C++
// #define PRUEBAS_SIN_VCL
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
#include "stdlib.h"
|
|
#include "stdio.h"
|
|
#include "conio.h"
|
|
#include "windows.h"
|
|
#define _verbose ACTIVA_EXPLICACION_PROCESOS
|
|
#include "LM2000.h"
|
|
|
|
#ifndef PRUEBAS_SIN_VCL
|
|
|
|
#include <vcl.h>
|
|
#pragma hdrstop
|
|
|
|
//#include "stdafx.h"
|
|
|
|
#pragma package(smart_init)
|
|
//---------------------------------------------------------------------------
|
|
// ValidCtrCheck is used to assure that the components created do not have
|
|
// any pure virtual functions.
|
|
//
|
|
|
|
static inline void ValidCtrCheck(TLm2000 *)
|
|
{
|
|
new TLm2000(NULL);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TLm2000::TLm2000(TComponent* Owner)
|
|
: TComponent(Owner)
|
|
#else
|
|
void __fastcall TLm2000::printfv( AnsiString msg )
|
|
{
|
|
printf( "%s\n", msg.c_str() );
|
|
}
|
|
|
|
__fastcall TLm2000::TLm2000(void)
|
|
#endif
|
|
{
|
|
LM_opened = false;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Construtor de clase, que inicializa los parámetros de comunicación
|
|
*/
|
|
__fastcall TLm2000::~TLm2000(void)
|
|
{
|
|
// Si el puerto aun sigue abierto, lo cerramos...
|
|
if ( LM_opened )
|
|
CierraPuerto();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
#ifndef PRUEBAS_SIN_VCL
|
|
namespace Lm2000
|
|
{
|
|
void __fastcall PACKAGE Register()
|
|
{
|
|
TComponentClass classes[1] = {__classid(TLm2000)};
|
|
RegisterComponents("JD soft.", classes, 0);
|
|
}
|
|
}
|
|
#endif
|
|
//---------------------------------------------------------------------------
|
|
#define ENTER_CARD_MEMORY "A"
|
|
// B: solo se usa por compatibilidad -[ NO IMPLEMENTADO ]-
|
|
#define CARD_NOT_VALID "C"
|
|
#define RTF_MOTIVE_NOT_STANDARD 0
|
|
#define RTF_CARD_CODE_UNKNOWN 1
|
|
#define RTF_MAGNETIC_CARD_EXPIRED 2
|
|
#define RTF_PERIOD_NOT_VALID 3
|
|
#define RTF_ANTIPASSBACK_ERROR 4
|
|
#define RTF_CARD_VERSION_NOT_VALID 5
|
|
#define RTF_CREDIT_INSUFFICIENT 6
|
|
#define DELETE_CARD_MEMORY "D"
|
|
#define CONFIGURE_MEMORY "E"
|
|
#define FMC_LONG_CODES 1
|
|
#define FMC_PIN 2
|
|
#define FMC_EXPIRATION 4
|
|
#define FMC_PREFIX_FREE 8
|
|
#define FMC_MINI_MEMORY 16
|
|
#define FMC_CARD_REVISION 32
|
|
#define WRITE_CHARS_ON_BAND "F"
|
|
#define READ_CHARS_ON_BAND "F?"
|
|
// G: CONFIGURA PREFIJOS -[ NO IMPLEMENTADO ]-
|
|
#define PROGRAMMING_PERIODS "H"
|
|
#define SIMPLE_INTERROGATION "I"
|
|
#define PROGRAM_OPERATION_PARAMETERS "J"
|
|
#define RESET_CLOCK "K"
|
|
// L: Configura los tipos de usuarios -[ NO IMPLEMENTADO ]-
|
|
#define CARD_VALID "R"
|
|
// S: Sustituido por 'C' -[ NO IMPLEMENTADO ]-
|
|
#define DELETE_ALL_CARD_MEMORY "T"
|
|
#define PASSAGE_OPENING "P"
|
|
#define SHOW_NEXT_TRANSIT "U"
|
|
#define SET_TIME "V"
|
|
|
|
// Secuencia de lectura correcta de tarjetas
|
|
#define INITIALIZE_READING "O?"
|
|
#define READ_CARD_MEMORY "A?"
|
|
#define SHOW_NEXT_MESSAGE "N?"
|
|
|
|
// B?: Inicializa la lectura de mensajes personales
|
|
// -[ NO IMPLEMENTADO ]-
|
|
|
|
// Secuencia de lectura de mensajes personales
|
|
// -[ NO IMPLEMENTADO ]-
|
|
#define INITIALIZE_READING_CM "B?"
|
|
#define READ_PERSONAL_MESSAGE "Y?"
|
|
#define SHOW_NEXT_PMESSAGE "D?"
|
|
|
|
|
|
#define REINITILIZE_TRANSIS_M "C?"
|
|
|
|
#define READ_MEMORY_CFG "E?"
|
|
// F?: Lee cfg caracteres de la banda -[ NO IMPLEMENTADO ]-
|
|
#define READ_PREFIXES "G?"
|
|
// H?: Lee periodos
|
|
#define READ_OPERATION_CFG "J?"
|
|
|
|
|
|
#define READ_FIRMWARE "I?"
|
|
#define READ_TIMER(X) "b?,X"
|
|
|
|
|
|
#define READ_SYSTEM_MESSAGE "X?"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Abre el puerto de comunicación "lpszrPortName"
|
|
Esta función debe ser llamada antes de cualquier otra comunicación;
|
|
*/
|
|
int __fastcall TLm2000::AbrePuerto(LPTSTR lpszPortName)
|
|
{
|
|
DWORD dwError;
|
|
DCB PortDCB;
|
|
COMMTIMEOUTS CommTimeouts;
|
|
|
|
// Antes de abrir, cerramos si asi procede
|
|
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 = 8; // Number of bits/bytes, 4-8
|
|
PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space
|
|
PortDCB.StopBits = ONESTOPBIT; // 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.
|
|
dwError = GetLastError ();
|
|
(printfv)( Format("Unable to configure the serial port\n%s\n", ARRAYOFCONST(("dwError")) ) );
|
|
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 = 5000;
|
|
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.
|
|
dwError = GetLastError ();
|
|
(printfv)( Format( "Unable to set the time-out parameters: %s", ARRAYOFCONST(("dwError")) ) );
|
|
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;
|
|
};
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Cierra el puerto, (siempre que este abierto) y libera los recursos pedidos
|
|
*/
|
|
void __fastcall TLm2000::CierraPuerto(void)
|
|
{
|
|
if ( LM_opened )
|
|
{
|
|
CloseHandle( LM_handle );
|
|
}
|
|
};
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Dada una cadena de entrada, genera el CheckSum de comprobación necesario,
|
|
devolviendo este al final.
|
|
*/
|
|
int __fastcall TLm2000::GeneraChecksum( char *cadena )
|
|
{
|
|
int CHK, i;
|
|
CHK = 0;
|
|
for ( i=0; cadena[i] != NULL; i++ )
|
|
{
|
|
CHK += cadena[i];
|
|
}
|
|
|
|
return ( CHK - ( (CHK / 10000)*10000 ) );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
NO SE PARA QUE ERA ESTO
|
|
*/
|
|
/*
|
|
int __fastcall:tieneRespuesta( char *CMD )
|
|
{
|
|
int dev = -1;
|
|
|
|
if ( strcmp( CMD, READ_FIRMWARE ) == 0 ) dev = 1;
|
|
|
|
return dev;
|
|
}
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
ObtenerRespuesta
|
|
Lee del puerto los datos pendientes del buffer
|
|
(solo lee lo que expulse el LM)
|
|
*/
|
|
char * __fastcall TLm2000::ObtenerRespuesta( char *rcv )
|
|
{
|
|
char buf[80], enviar[80];
|
|
DWORD CHK, chkF = 0;
|
|
int i = 0;
|
|
DWORD dwCommModemStatus;
|
|
|
|
if ( LM_opened )
|
|
{
|
|
|
|
/*
|
|
03-02-2002 ELIMINADO PARA EVITAR QUEDAR COLGADO A LA ESPERA DEL LEGO
|
|
Esperemos que los TIME-OUTS funcienen BIEN sin esto.
|
|
// 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 ( rcv[i] == 13 ) break; else i++;
|
|
} else {
|
|
// if ( CHK == 0 )
|
|
if ( (++chkF) >= 10 )
|
|
{
|
|
sprintf( rcv, "ERROR: Respuesta fuera de tiempo" );
|
|
return rcv;
|
|
}
|
|
}
|
|
}
|
|
rcv[i+1] = '\0';
|
|
|
|
// Verificamos la respuesta del lector
|
|
if ( i > 10 && i < 75)
|
|
{
|
|
char *ptr;
|
|
// Generamos nuestro CHECKSUM de la respuesta
|
|
strcpy( buf, rcv ); buf[ i - 4 ] = '\0';
|
|
CHK = GeneraChecksum( buf );
|
|
// Aislamos el CHECKSUM de la respuesta
|
|
strcpy( buf, rcv ); ptr = buf + i - 4; buf[ i ] = '\0';
|
|
// Comparamos los CHECKSUM
|
|
sprintf( enviar, "%04d", CHK );
|
|
if ( strcmp( enviar, ptr ) != 0 )
|
|
{
|
|
strcpy( enviar, rcv );
|
|
sprintf( rcv, "ERROR CHECKSUM: (%04d) - %s", CHK, enviar );
|
|
}
|
|
} else
|
|
sprintf( rcv, "ERROR: Respuesta de longitud incorrecta" );
|
|
} else {
|
|
sprintf( rcv, "ERROR: LM no abierto" );
|
|
}
|
|
|
|
#ifdef _verbose
|
|
(printfv)( Format("Recibido: %s\n", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
|
|
return rcv;
|
|
};
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Envia el comando CMD al lector ID, devolviendo la respuesta 'rcv'
|
|
*/
|
|
char * __fastcall TLm2000::EnviarComando( char *CMD, int ID, char *rcv )
|
|
{
|
|
char buf[80], enviar[80];
|
|
DWORD CHK;
|
|
if ( LM_opened )
|
|
{
|
|
sprintf( buf, "L%03d:%s,", ID, CMD );
|
|
CHK = GeneraChecksum( buf );
|
|
sprintf( enviar, "%s%04d\r", buf, CHK );
|
|
|
|
#ifdef _verbose
|
|
(printfv)( Format("\nEnviado: %s\n", ARRAYOFCONST((enviar)) ) );
|
|
#endif
|
|
|
|
WriteFile( LM_handle, enviar, strlen(enviar), &CHK, NULL );
|
|
|
|
ObtenerRespuesta( rcv );
|
|
|
|
} else
|
|
sprintf( rcv, "ERROR: LM no abierto" );
|
|
|
|
return rcv;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Procesa el transito devuelto tras una llamada a CMD=I
|
|
*/
|
|
void __fastcall TLm2000::ProcesaTransito( char *FGT, char *TPT, char *CDT, char *O, char *DTT, char *CTT, char *ETT )
|
|
{
|
|
#ifdef _verbose
|
|
(printfv)( Format("\nFGT %s\nTPT: %s\nCDT: %s\nO: %s\nDTT: %s\nCTT: %s\nETT: %s\n", ARRAYOFCONST((FGT, TPT, CDT, O, DTT, CTT, ETT)) ) );
|
|
#endif
|
|
#ifndef PRUEBAS_SIN_VCL
|
|
if ( FOnProcesaTransito ) (FOnProcesaTransito)( FGT, TPT, CDT, O, DTT, CTT, ETT );
|
|
#endif
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Dada una cadena de parámetros delimitados por coma ',', obtiene y de vuelve
|
|
en 'prm' el parametro 'narg'-esimo.
|
|
*/
|
|
char * __fastcall TLm2000::ObtenerParametro( char *cadena, int narg, char *prm )
|
|
{
|
|
int i;
|
|
char *inicio, *fin;
|
|
|
|
inicio = cadena;
|
|
fin = cadena;
|
|
|
|
// Delimitación del parámetro
|
|
for ( i=0; *fin != '\0' && i < narg; fin++ )
|
|
{
|
|
// Si es el comienzo de un nuevo parametro...
|
|
if ( *fin == ',' )
|
|
{
|
|
i++;
|
|
if ( i < narg )
|
|
inicio = (fin + 1);
|
|
}
|
|
}
|
|
|
|
// Longitud del parametro
|
|
i = fin - inicio - 1;
|
|
// Copia aislada del parámetro
|
|
strncpy( prm, inicio, i );
|
|
prm[ i ] = '\0';
|
|
|
|
return prm;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Esta es la función que debe ser redefinida...
|
|
*/
|
|
// bool BuscaTarjeta( int FGA, int TPA, int CDA, int *TPR, int *PNR, char *message )
|
|
// {
|
|
// bool enc = false;
|
|
//
|
|
// #ifdef _verbose
|
|
// (printfv)( "Localizando tarjeta: (%d)-%d-%d", FGA, TPA, CDA );
|
|
// #endif
|
|
// // Localizamos la tarjeta
|
|
// if ( /* LOCALIZADA */ 1 )
|
|
// {
|
|
// *TPR = 0;
|
|
// *PNR = 0;
|
|
// sprintf( message, "ACCESO PERMITIDOwww.infdj.com" );
|
|
// enc = true;
|
|
// } else {
|
|
// sprintf( message, "ACCESO DENEGADOwww.infdj.com" );
|
|
// enc = false;
|
|
// }
|
|
//
|
|
// return enc;
|
|
// }
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Procesa una tarjeta despues de un SIMPLE_INTERROGATION
|
|
*/
|
|
bool __fastcall TLm2000::ProcesaTarjeta( int ID, char *msg )
|
|
{
|
|
char buff[80], rcv[80];
|
|
char message[80];
|
|
int FGA, TPA, CDA, TPR, PNR;
|
|
#ifdef _verbose
|
|
(printfv)( Format("ProcesaTarjeta: %s", ARRAYOFCONST((msg)) ) );
|
|
#endif
|
|
|
|
// Obtenemos los datos de la tarjeta
|
|
FGA = atoi( ObtenerParametro( msg, 2, buff ) );
|
|
TPA = atoi( ObtenerParametro( msg, 3, buff ) );
|
|
CDA = atoi( ObtenerParametro( msg, 4, buff ) );
|
|
|
|
|
|
// La cotejamos con nuestra base de datos ( CDA )
|
|
#ifdef PRUEBAS_SIN_VCL
|
|
if ( 1 )
|
|
#else
|
|
if ( (FOnBuscaTarjeta) && (FOnBuscaTarjeta)( ID, FGA, TPA, CDA, &TPR, &PNR, message ) )
|
|
#endif
|
|
{
|
|
// ¿Tiene permiso?
|
|
sprintf( buff, "%s, %d, %d,%s", CARD_VALID, TPR, PNR, message );
|
|
EnviarComando( buff, ID, rcv );
|
|
|
|
if ( rcv[5] == 'X' )
|
|
{
|
|
// Necesitamos esperar a que se libere la linea de comunicación
|
|
Sleep( 1000 );
|
|
PassageOpening( ID, (FGA & 0x0008) ? 1 : 2 );
|
|
}
|
|
|
|
} else {
|
|
// Si no esta...
|
|
sprintf( buff, "%s, %d,%s", CARD_NOT_VALID, RTF_MOTIVE_NOT_STANDARD, message );
|
|
EnviarComando( buff, ID, rcv );
|
|
}
|
|
|
|
return ( rcv[5] == 'X' );
|
|
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Realiza una InterrogaciónSimple
|
|
*/
|
|
char * __fastcall TLm2000::SimpleInterrogation( int ID, char *rcv )
|
|
{
|
|
char prm[7][20];
|
|
|
|
|
|
EnviarComando( SIMPLE_INTERROGATION, ID, rcv );
|
|
|
|
// Tratamos las posibles respuestas a una Interrogación Simple
|
|
switch( rcv[5] )
|
|
{
|
|
// Transit to download
|
|
case 'T':
|
|
#ifdef _verbose
|
|
(printfv)( "Transit to download\n" );
|
|
#endif
|
|
ProcesaTransito( ObtenerParametro( rcv, 2, prm[0] ),
|
|
ObtenerParametro( rcv, 3, prm[1] ),
|
|
ObtenerParametro( rcv, 4, prm[2] ),
|
|
ObtenerParametro( rcv, 5, prm[3] ),
|
|
ObtenerParametro( rcv, 6, prm[4] ),
|
|
ObtenerParametro( rcv, 7, prm[5] ),
|
|
ObtenerParametro( rcv, 8, prm[6] ) );
|
|
EnviarComando( SHOW_NEXT_TRANSIT, ID, rcv );
|
|
break;
|
|
// Information to Request
|
|
case 'H':
|
|
#ifdef _verbose
|
|
(printfv)( "Information to Request\n" );
|
|
#endif
|
|
ProcesaTarjeta( ID, rcv );
|
|
break;
|
|
// Alarm
|
|
case 'A':
|
|
#ifdef _verbose
|
|
(printfv)( "Alarm\n" );
|
|
#endif
|
|
break;
|
|
// No information to communicate
|
|
case 'R':
|
|
#ifdef _verbose
|
|
(printfv)( "No information to communicate\n" );
|
|
#endif
|
|
break;
|
|
// -- error --
|
|
default:
|
|
#ifdef _verbose
|
|
(printfv)( "ERROR: SimpleInterrogration ERROR de RESPUESTA\n" );
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return rcv;
|
|
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee una tarjeta de la memoria del lector
|
|
*/
|
|
bool __fastcall TLm2000::ReadCardMemory( int ID, TCard *CRD )
|
|
{
|
|
bool hay_mas_tarjetas = false;
|
|
char buff[80], rcv[80];
|
|
|
|
EnviarComando( READ_CARD_MEMORY, ID, rcv );
|
|
if ( rcv[0] != 'E' )
|
|
{
|
|
hay_mas_tarjetas = !( rcv[5] == 'X' && rcv[7] == '1' );
|
|
if ( hay_mas_tarjetas )
|
|
{
|
|
// Procesamos los parámetros
|
|
CRD->FLG = atol( ObtenerParametro( rcv, 2, buff ) ); // FLG
|
|
CRD->TYP = atol( ObtenerParametro( rcv, 3, buff ) ); // TYP
|
|
CRD->CDA = atol( ObtenerParametro( rcv, 4, buff ) ); // CDA
|
|
CRD->PIN = atol( ObtenerParametro( rcv, 5, buff ) ); // PIN
|
|
CRD->GIS = atol( ObtenerParametro( rcv, 6, buff ) ); // GIS
|
|
CRD->MES = atol( ObtenerParametro( rcv, 7, buff ) ); // MES
|
|
CRD->ANS = atol( ObtenerParametro( rcv, 8, buff ) ); // ANS
|
|
CRD->ORS = atol( ObtenerParametro( rcv, 9, buff ) ); // ORS
|
|
CRD->MIS = atol( ObtenerParametro( rcv, 10, buff ) ); // MIS
|
|
CRD->SES = atol( ObtenerParametro( rcv, 11, buff ) ); // SES
|
|
CRD->REV = atol( ObtenerParametro( rcv, 12, buff ) ); // REV
|
|
CRD->CRD = atol( ObtenerParametro( rcv, 13, buff ) ); // CRD
|
|
#ifdef _verbose
|
|
(printfv)( Format("FLG: %ld\nTYP: %ld\nCDA: %ld\nPIN: %ld\nGIS: %ld\nMES: %ld\nANS: %ld\nORS: %ld\nMIS: %ld\nSES: %ld\nREV: %ld\nCRD: %ld\n", ARRAYOFCONST((CRD->FLG, CRD->TYP, CRD->CDA, CRD->PIN, CRD->GIS, CRD->MES, CRD->ANS, CRD->ORS, CRD->MIS, CRD->SES, CRD->REV, CRD->CRD)) ) );
|
|
(printfv)( "CARD_FLAG\n--------\n" );
|
|
int nFLAG = CRD->FLG;
|
|
(printfv)( Format("EXTERNAL READER: %s\nINTERNAL READER: %s\nFROM LEFT TO RIGHT: %s\nFROM RIGHT TO LEFT %s\n",ARRAYOFCONST(( (nFLAG & 0x08) ? "SI":"NO",
|
|
(nFLAG & 0x04) ? "SI":"NO",
|
|
(nFLAG & 0x02) ? "SI":"NO",
|
|
(nFLAG & 0x01) ? "SI":"NO")) ) );
|
|
#endif
|
|
}
|
|
} else {
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR READ_CARD_MEMORY: %s\n", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
}
|
|
|
|
return hay_mas_tarjetas;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Debe devolver la lista de tarjetas de la memoria completa
|
|
(No implento el parametro de salida de momento)
|
|
*/
|
|
void __fastcall TLm2000::ReadEntireCardMemory( int ID )
|
|
{
|
|
char rcv[80];
|
|
TCard CRD;
|
|
|
|
EnviarComando( INITIALIZE_READING, ID, rcv );
|
|
if ( rcv[0] != 'E' )
|
|
{
|
|
while( ReadCardMemory( ID, &CRD ) )
|
|
{
|
|
// Procesar Tarjeta
|
|
///***///
|
|
EnviarComando( SHOW_NEXT_MESSAGE, ID, rcv );
|
|
};
|
|
} else {
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR FIRST_CARD: %s\n", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
}
|
|
}
|
|
// #############################################################################
|
|
// #############################################################################
|
|
// #############################################################################
|
|
// #############################################################################
|
|
// #############################################################################
|
|
// #############################################################################
|
|
// #############################################################################
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Introducimos tarjetas en la Memoria
|
|
*/
|
|
int __fastcall TLm2000::EnterCardMemory( int ID, TCard *CRD )
|
|
{
|
|
int dev;
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", ENTER_CARD_MEMORY,
|
|
CRD->FLG, CRD->TYP, CRD->CDA, CRD->PIN, CRD->GIS, CRD->MES,
|
|
CRD->ANS, CRD->ORS, CRD->MIS, CRD->SES, CRD->REV, CRD->CRD );
|
|
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] == 'X' )
|
|
{
|
|
dev = atol( ObtenerParametro( rcv, 2, enviar ) );
|
|
} else
|
|
if ( rcv[5] == 'E' )
|
|
{
|
|
switch( rcv[7] )
|
|
{
|
|
case '6':
|
|
dev = -6;
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR EnterCardMemory Memory full: %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
break;
|
|
case '8':
|
|
dev = -8;
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR EnterCardMemory Card code below acceptable minimum: %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
break;
|
|
default:
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR EnterCardMemory (SIN IDENTIFICAR): %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
}
|
|
|
|
}
|
|
return dev;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Elimina del LM'ID' la tarjeta TIP/COD
|
|
*/
|
|
int __fastcall TLm2000::DeleteCardMemory( int ID, int TIP, int COD )
|
|
{
|
|
int dev;
|
|
char enviar[80], rcv[80];
|
|
sprintf( enviar, "%s,0,%d,%d", DELETE_CARD_MEMORY, TIP, COD );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] == 'X' )
|
|
dev = atoi( ObtenerParametro( rcv, 2, enviar ) );
|
|
else
|
|
dev = 0;
|
|
|
|
return dev;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Elimina TODAS las tarjetas de la memoria
|
|
*/
|
|
int __fastcall TLm2000::DeleteAllCardMemory( int ID, int TIP )
|
|
{
|
|
return DeleteCardMemory( ID, TIP, TIP );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee la configuración del Lector ID
|
|
*/
|
|
RMem * __fastcall TLm2000::ReadMemoryCFG( int ID, RMem *mem )
|
|
{
|
|
char rcv[80], prm[80];
|
|
|
|
EnviarComando( READ_MEMORY_CFG, ID, rcv );
|
|
|
|
mem->FMC = atoi( ObtenerParametro( rcv, 2, prm ) );
|
|
mem->MAC = atoi( ObtenerParametro( rcv, 3, prm ) );
|
|
mem->LFN = atoi( ObtenerParametro( rcv, 4, prm ) );
|
|
mem->NCR = atoi( ObtenerParametro( rcv, 5, prm ) );
|
|
mem->CMN = atoi( ObtenerParametro( rcv, 6, prm ) );
|
|
mem->CMX = atoi( ObtenerParametro( rcv, 7, prm ) );
|
|
mem->NBN = atoi( ObtenerParametro( rcv, 8, prm ) );
|
|
mem->NMP = atoi( ObtenerParametro( rcv, 9, prm ) );
|
|
mem->NFA = atoi( ObtenerParametro( rcv, 10, prm ) );
|
|
mem->RMS = atoi( ObtenerParametro( rcv, 11, prm ) );
|
|
mem->MCA = atoi( ObtenerParametro( rcv, 12, prm ) );
|
|
mem->MCR = atoi( ObtenerParametro( rcv, 13, prm ) );
|
|
|
|
#ifdef _verbose
|
|
(printfv)( Format("%s\n", ARRAYOFCONST((rcv)) ) );
|
|
(printfv)( Format("FMC: %d\nMAC: %d\nLFN: %d\nNCR: %d\nCMN: %d\nCMX: %d\nNBN: %d\nNMP: %d\nNFA: %d\nRMS: %d\nMCA: %d\nMCR: %d\n", ARRAYOFCONST((
|
|
mem->FMC, mem->MAC, mem->LFN, mem->NCR, mem->CMN, mem->CMX,
|
|
mem->NBN, mem->NMP, mem->NFA, mem->RMS, mem->MCA, mem->MCR)) ) );
|
|
#endif
|
|
|
|
return mem;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Configura el Lector ID
|
|
*/
|
|
bool __fastcall TLm2000::ConfigureMemory( int ID, RMem *mem )
|
|
{
|
|
bool dev;
|
|
char enviar[80], rcv[80];
|
|
// Verificamos que todos los parámetros sean correctos
|
|
if ( ((mem->FMC) & ( FMC_LONG_CODES + FMC_MINI_MEMORY )) )
|
|
{
|
|
#ifdef _verbose
|
|
(printfv)( "Error ConfigureMemory: FMC_LONG_CODES y FMC_MINI_MEMORY son incompatibles" );
|
|
#endif
|
|
dev = false;
|
|
} else {
|
|
// Configuramos la memoria
|
|
sprintf( enviar, "%s,%s,,%s,,%s,%s,%s,%s,%s,%s,%s,%s", CONFIGURE_MEMORY,
|
|
mem->FMC, mem->LFN, /*mem->NCR, */ mem->CMN, mem->CMX, mem->NBN,
|
|
mem->NMP, mem->NFA, mem->RMS, mem->MCA, mem->MCR );
|
|
EnviarComando( enviar, ID, rcv );
|
|
if ( rcv[5] == 'E' )
|
|
{
|
|
#ifdef _verbose
|
|
(printfv)( "ERROR ConfigureMemory: MEMORY IS FULL ó PAMARETERS ARE INCORRECT" );
|
|
#endif
|
|
dev = false;
|
|
}
|
|
if ( rcv[5] == 'X' )
|
|
{
|
|
int resp = atoi( ObtenerParametro( rcv, 2, enviar ) );
|
|
#ifdef _verbose
|
|
(printfv)( "ConfigureMemory: " );
|
|
switch( resp )
|
|
{
|
|
case 0: (printfv)( "Memory not affected" ); break;
|
|
case 1: (printfv)( "Transit memory" ); break;
|
|
case 2: (printfv)( "Transit memory + personal messages memory" ); break;
|
|
case 3: (printfv)( "Transit memory + personal messages memory + periods" ); break;
|
|
default:
|
|
(printfv)( Format("Card Memory [ %d ]", ARRAYOFCONST((resp)) ) ); break;
|
|
}
|
|
dev = true;
|
|
#endif
|
|
}
|
|
}
|
|
return dev;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Programación de los Periodos
|
|
*/
|
|
bool __fastcall TLm2000::ProgrammingPeriods( int ID, int NFS, int PBN, char *StarTime, char *EndTime, int GIF )
|
|
{
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%s,%s,%d", PROGRAMMING_PERIODS, NFS, PBN, StarTime, EndTime, GIF );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
#ifdef _verbose
|
|
if ( rcv[5] == 'E' )
|
|
(printfv)( Format("ERROR ProgrammingPeriods Arguments incorrect: %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
|
|
return ( rcv[5] == 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Configura el número de caracteres en la banda
|
|
*/
|
|
bool __fastcall TLm2000::SetCharsOnBand( int ID, CAB *cab )
|
|
{
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%d,%d,%d,%d,%d,%d", WRITE_CHARS_ON_BAND, cab->GAP, cab->LEP, cab->GAC, cab->LEC, cab->GAR, cab->LER, cab->GDI, cab->GDF );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
#ifdef _verbose
|
|
if ( rcv[5] == 'E' )
|
|
(printfv)( Format("ERROR SetCharsOnBand: %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
|
|
return ( rcv[5] == 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Parametros de operacion del programa
|
|
*/
|
|
bool __fastcall TLm2000::ProgramOperationParameters( int ID, POP *pop )
|
|
{
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%d,%d,%d,%d,%d,%d", PROGRAM_OPERATION_PARAMETERS, pop->BKN, pop->BKP, pop->PRN, pop->MCL, pop->MCK, pop->ENF, pop->SNV, pop->ENI );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
return ( rcv[5] == 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Activar los reles de salida
|
|
1 Internal Reader
|
|
2 External Reader
|
|
3 Output 1
|
|
4 Output 2
|
|
*/
|
|
bool __fastcall TLm2000::PassageOpening( int ID, int Passage )
|
|
{
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d", PASSAGE_OPENING, Passage );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
return ( rcv[5] == 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Reconfigura el reloj
|
|
*/
|
|
bool __fastcall TLm2000::ResetClock( int ID, RClock *clock )
|
|
{
|
|
int err;
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%d,%d,%d,%d", RESET_CLOCK, clock->GIA, clock->MEA, clock->ANA, clock->ORA, clock->MIA, clock->SEA );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
#ifdef _verbose
|
|
if ( rcv[5] == 'E' )
|
|
{
|
|
err = atoi( ObtenerParametro( rcv, 2, enviar ) );
|
|
(printfv)( Format( "ERROR ResetClock: %s", ARRAYOFCONST(( (err == 0) ? "Date incorrect" : "Time incorrect")) ) );
|
|
}
|
|
#endif
|
|
|
|
|
|
return ( rcv[5] == 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee los caracteres en la banda
|
|
*/
|
|
bool __fastcall TLm2000::GetCharsOnBand( int ID, CAB *cab )
|
|
{
|
|
int dev;
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s", READ_CHARS_ON_BAND );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] != 'E' )
|
|
{
|
|
dev = true;
|
|
cab->GAP = atoi( ObtenerParametro( rcv, 2, enviar ) );
|
|
cab->LEP = atoi( ObtenerParametro( rcv, 3, enviar ) );
|
|
cab->GAC = atoi( ObtenerParametro( rcv, 4, enviar ) );
|
|
cab->LEC = atoi( ObtenerParametro( rcv, 5, enviar ) );
|
|
cab->GAR = atoi( ObtenerParametro( rcv, 6, enviar ) );
|
|
cab->LER = atoi( ObtenerParametro( rcv, 7, enviar ) );
|
|
cab->GDI = atoi( ObtenerParametro( rcv, 8, enviar ) );
|
|
cab->GDF = atoi( ObtenerParametro( rcv, 9, enviar ) );
|
|
#ifdef _verbose
|
|
(printfv)( Format("ReadCharsOnBand: %d", ARRAYOFCONST((dev)) ) );
|
|
#endif
|
|
} else {
|
|
dev = false;
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR ReadCharsOnBand: %s", ARRAYOFCONST((rcv)) ) );
|
|
#endif
|
|
}
|
|
|
|
return dev;
|
|
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee los prefijos activos
|
|
*/
|
|
int __fastcall TLm2000::ReadingPrefixes( int ID, int NPR )
|
|
{
|
|
int dev;
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d", READ_PREFIXES, NPR );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] != 'E' )
|
|
{
|
|
dev = atoi( ObtenerParametro( rcv, 2, enviar ) );
|
|
#ifdef _verbose
|
|
(printfv)( Format("ReadingPrefixes: %d", ARRAYOFCONST((dev)) ) );
|
|
#endif
|
|
} else {
|
|
dev = -1;
|
|
#ifdef _verbose
|
|
(printfv)( Format("ERROR ReadingPrefixes: NPR argument", ARRAYOFCONST((dev)) ) );
|
|
#endif
|
|
}
|
|
|
|
return dev;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee los mensajes personales
|
|
*/
|
|
bool __fastcall TLm2000::ReadPersonalMessage( int ID )
|
|
{
|
|
char rcv[80], prm[80];
|
|
int TPM, CDM, MSU;
|
|
|
|
EnviarComando( READ_PERSONAL_MESSAGE, ID, rcv );
|
|
|
|
TPM = atoi( ObtenerParametro( rcv, 2, prm ) );
|
|
CDM = atoi( ObtenerParametro( rcv, 3, prm ) );
|
|
MSU = atoi( ObtenerParametro( rcv, 4, prm ) );
|
|
|
|
#ifdef _verbose
|
|
(printfv)( Format("TPM: %d\nCDM: %d\nMSU: %d\n-------\n", ARRAYOFCONST((TPM, CDM, MSU)) ) );
|
|
#endif
|
|
|
|
return ( rcv[5] != 'X' );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee todos los mensajes personales
|
|
*/
|
|
void __fastcall TLm2000::ReadAllPersonalMessage( int ID )
|
|
{
|
|
char rcv[80];
|
|
|
|
EnviarComando( INITIALIZE_READING_CM, ID, rcv );
|
|
|
|
if ( rcv[5] == 'X' )
|
|
{
|
|
while( ReadPersonalMessage( ID ) )
|
|
{
|
|
EnviarComando( SHOW_NEXT_PMESSAGE, ID, rcv );
|
|
};
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
N.P.I de lo que hace esto
|
|
*/
|
|
void __fastcall TLm2000::SetTime( int ID, TSD *tsd )
|
|
{
|
|
char enviar[80], rcv[80];
|
|
|
|
sprintf( enviar, "%s,%d,%d,%d,%d,%d,%d,%d,", SET_TIME, tsd->CHN, tsd->GSL, tsd->MMS, tsd->ASL, tsd->HSL, tsd->MSL, tsd->SSL );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] == 'X' )
|
|
{
|
|
/*
|
|
while( ReadPersonalMessage( ID ) )
|
|
{
|
|
EnviarComando( SHOW_NEXT_PMESSAGE, ID, rcv );
|
|
};
|
|
*/
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
Lee los mensajes del sistema
|
|
*/
|
|
char * __fastcall TLm2000::ReadSystemMessages( int ID, int IDmsg, char *rcv )
|
|
{
|
|
char enviar[80];
|
|
|
|
sprintf( enviar, "%s,%d,", READ_SYSTEM_MESSAGE, IDmsg );
|
|
EnviarComando( enviar, ID, rcv );
|
|
|
|
if ( rcv[5] == 'E' )
|
|
{
|
|
#ifdef _verbose
|
|
sprintf( rcv, "ERROR ReadSystemMessage: IDmsg fuera de RANGO" );
|
|
#endif
|
|
|
|
}
|
|
return rcv;
|
|
}
|