Ver Mensaje Individual
  #1  
Antiguo 26-03-2014
Avatar de JULIPO
JULIPO JULIPO is offline
Miembro
 
Registrado: ene 2006
Ubicación: Bogota Colombia
Posts: 187
Reputación: 19
JULIPO Va por buen camino
Problema con hilos para conexion de biometricas

Hola estoy desarrollando una aplicacion de control de acceso y asistencia con lectoras biometricas de zksoftware, estoy utilizando delphi xe4 la base de datos es mysql y para poder conectarnos via TCP/IP con las lectoras utilizamos un SDK Zkemkeeper que entrega el fabricante de las lectoras.

el problema que tenemos es el siguiente el proceso de conexion a las lectoras no es rapido si trabajamos con pocas lectoras pues los tiempos de conexion son aceptables pero si trabajamos con mas de 4 lectoras ya se hace muy lento el proceso y la informacion en las lectoras 4,5,6..n pueden demorarse hasta 3 o 4 minutos, probamos entonces con la creacion de hilos de ejecucion la idea es que se cree un hilo con cada lectora de manera que si hay problemas con la conexion de alguna de las lectoras las otras puedan recibir la informacion de manera rapida.

vamos a ver el ejemplo
Código Delphi [-]
  tprueba = class(Tthread)
  lectora1:tczkem;
  var
   ejecutando,conectado:boolean;
   error,error1,puerto1,nolectora1,ttf,version1,I:integer;
   dirip1,valor1,valor2:string;
   version:widestring;
   descripcionordenes:Ansistring;
  protected
    procedure actualiza;
    procedure actualiza1;
    constructor create(dirip:string;nolectora,puerto:integer); overload;
  public
    procedure Execute; override;
    procedure conectada(sender:Tobject);
    procedure desconexiondelec(sender:tobject);
    procedure alarma(sender: tobject; tipoalarma, nousuario,
      verificada: integer);
    procedure estadodoor(sender: tobject; tipoevento: integer);
    procedure grabacionhuellas(sender: tobject;
      EnrollNumber, FingerIndex, ActionResult, TemplateLength: integer);
    procedure huellapasa(sender:Tobject);
    procedure grabarusuario(lectora, nousuario, administrador: integer;
      nick: string; validar1: boolean);
    procedure recepciondatos(sender: tobject; EnrollNumber, IsInValid, AttState,
      VerifyMethod, Year, Month, Day, Hour, Minute, Second: integer);
    procedure tiempo1(sender: tobject);
    procedure tiempo2(novalor,limite:integer);
    Function descError:integer;
    //rutinas para trabajo de las lectoras
    Procedure validaruser(lectora,nousuario:integer;validar1:boolean);
    Procedure Borrarusuario(NoLectora3,Nousuario1:integer);
    Procedure BorrarHuella(NoLectora2,Nousuario2,Nohuella2:integer);
    Procedure GrabarHuella(nolectora4,nousuario4,nohuella4:integer;strhuella:widestring);
    Procedure Actualizatiempo(nolectora4:integer);
    Procedure Establececom;
    Procedure escribeordenes;
    Procedure conectarlectora;
  end;

desde el programa principal hacemos lo siguiente creamos un arreglo dinamico dependiendo de de la cantidad de lectoras que esten registradas en la base de datos
y creamos un thread para cada uno de los items del arreglo.
Código Delphi [-]
Var
 iniciolec:array of tprueba;
 Begin
 procedure TForm1.FormCreate(Sender: TObject);
begin
 try
  datamod.SQLConnection1.Connected:=true;
 except
   showmessage('error de conexion a la base de datos revise parametros y ejecute nuevamente');
   application.Terminate;
 end;
 if not datamod.Lectoras.Active then
  datamod.Lectoras.Active:=True;
 if datamod.Clectoras.Active then
  datamod.Clectoras.Close
 else
  begin
   datamod.Clectoras.Filter:='conexion=''TCP'' and marca=''ZKSOFT''';
   datamod.Clectoras.Filtered:=True;
   datamod.Clectoras.Active:=True;
  end;
 if not datamod.Lectoras1.Active then
  datamod.Lectoras1.Active:=True;
 if datamod.Clectoras1.Active then
  datamod.Clectoras1.Close;
 if not datamod.Usuarios.Active then
  datamod.Usuarios.Active:=True;
 if not datamod.Huellas.Active then
  datamod.Huellas.Active:=True;
 if not datamod.Actualiza.Active then
  datamod.Actualiza.Active:=True;
 if not datamod.ordenes.Active then
  datamod.ordenes.Active:=True;
 if not datamod.eventos.Active then
  datamod.eventos.Active:=True;
 if not datamod.ceventos.Active then
  datamod.ceventos.Active:=True;
 if not datamod.eventoslec.Active then
  datamod.eventoslec.Active:=True;
 contlec:=datamod.Clectoras.RecordCount;
 SetLength(iniciolec,datamod.Clectoras.RecordCount);
 SetLength(estlec,datamod.Clectoras.RecordCount);
 SetLength(vallec,datamod.Clectoras.RecordCount);
 datamod.Clectoras.First;
 while not datamod.Clectoras.Eof do
  begin //Grabamos en la base de datos el Status de lectora desconectada
   datamod.Clectoras.Edit;
   datamod.Clectoras.FieldByName('statuscon').AsInteger:=0;
   datamod.Clectoras.FieldByName('lostcon').AsInteger:=0;
   datamod.Clectoras.Post;
   datamod.Clectoras.Next;
  end;
 varlec:=0;
 datamod.Clectoras.First;
 while not datamod.Clectoras.Eof do
  begin
    vallec[varlec]:=datamod.Clectoras.FieldByName('nolectora').AsInteger;
    iniciolec[varlec]:=tprueba.create(datamod.Clectoras.FieldByName('direccionip').AsAnsiString,vallec[varlec],4370);
    iniciolec[varlec].Priority:=tplower;
    varlec:=varlec+1;
    datamod.Clectoras.Next;
  end;
 timer1.Interval:=1000;
 timer1.Enabled:=True;
 timer2.Interval:=1000;
 timer2.Enabled:=True;
 actualizahoralec.Enabled:=True;
end;
constructor tprueba.create(dirip:string;nolectora,puerto:integer);
begin
  inherited create(True);
  dirip1:=dirip;
  nolectora1:=nolectora;
  puerto1:=puerto;
  lectora1:=tczkem.Create(nil);
  lectora1.Name := 'lectora' + Inttostr(nolectora);
  lectora1.Tag := nolectora;
  lectora1.OnDisConnected := Desconexiondelec;
  lectora1.OnConnected:= conectada;
  lectora1.OnAlarm := alarma;
  lectora1.OnDoor := estadodoor;
  lectora1.OnEnrollFinger := grabacionhuellas;
  lectora1.OnAttTransaction := recepciondatos;
  timer1:=Ttimer.Create(nil);
  timer1.Enabled:=false;
  timer1.Interval:=1000;
  timer1.Tag:=1;
  timer1.OnTimer:=tiempo1;
end;
procedure tprueba.Execute;
begin
 ejecutando:=true;
 lectora1.Connect_Net(dirip1, puerto1);
 if conectado then
  begin
   lectora1.RegEvent(nolectora1, 65535);//65535 todos los eventos}
   lectora1.RefreshData(nolectora1);
   if lectora1.IsTFTMachine(nolectora1) then
      ttf := 1
    else
      ttf := 0;
    lectora1.GetSysOption(nolectora1, '~ZKFPVersion', version);
    if version = '10' then
      version1 := 10
    else
      version1 := 9;
  end;
  ejecutando:=FalsE;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 timer1.Enabled:=False;
 timer1.Interval:=30000;
 varlec:=0;
 while varlec''<''contlec do
  begin
   if iniciolec[varlec].Suspended then
     iniciolec[varlec].Resume
   else
    begin
     if not iniciolec[varlec].conectado then
      begin
       if not iniciolec[varlec].ejecutando then
        begin
         if not iniciolec[varlec].Timer1.Enabled then
          begin
           iniciolec[varlec].Timer1.Enabled:=True;//este timer verifica la conexion de las lectoras cada 30 segundos si no se logra la conexion
          end;
        end;
      end;
    end;
   varlec:=varlec+1;
  end;
 timer1.Enabled:=True;
end;
 End.

El problema es que cuando la lectora esta en linea el software funciona muy bien, pero si hay una lectora desconectada todo el programa incluyendo el principal se queda colgado esperando el status de la conexion de esa lectora y no se si estoy en un error pero la idea de los thread es que cada uno se comporte de manera independiente.

cual sera el problema
__________________
No basta con saber es necesario aplicar lo que se sabe, no basta con querer hacer las cosas es necesario hacerlas
Goethe
Responder Con Cita