unit unettoposclientutils;
interface
(*** rch@enero2012

esta unidad está pensada para facilitar la escritura de aplicaciones
clientes de la nettopos.
Se supone que solo un hilo de la aplicación llama a la librería.

**)
uses
  Classes, SysUtils,
  xmatdefs, unettopos, unettopostypes, uconstantes_nettopos, ubuffrw;

var
  idAplic: cardinal;
  NombreAplic: string;

function AlInicio( xNombreAplic: string; xidAplic: cardinal ): boolean;
procedure AlFinal;

(* retorna un identificador único de tarea dentro del ambito de la aplicación.
Sirve para mandarlo en los comunicados para poder relacionar las respuestas
con las peticiones en el caso de mensajes asíncronos *)
function getNextIdTarea: cardinal;

(* Retorna un array con los identificadores de los nodos registrados actualmente
en la red nettpos en el servidor web del IIE.
Los nodos puden estar Vivos o Muertos, no se retorna información al respecto.
Al inciarce cada Topo marca su presencia mediante un llamado a un servicio
del servidor web del IIE - FING. Este es un mecanismo de asignación de identificadores
únicos a los topos y de mantenimiento de una lista de topos registrados.
*)
function IIE_NodosRegistrados: TDAOfNCardinal;


(*
MemoADD ----- Servicio del Topo -----------

MemoADD es para prueba. Envía un mensaje al TOPO en el NODO destino
y el TOPO destino envía el mensaje MSGR_TOPO_MEMO_ADD para indicar que recibió
el texto.
Con la función post_MemoADD , el envío es asíncrono. Se envía el mensaje y la
función retorna en forma inmediata. La aplicación deberá preocuparse de
manejar el mensaje de respuesta MSGR_TOPO_MEMO_ADD.
Con la función call_MemoADD , el envío del mesaje es síncrono. En este caso
se realiza el envío y la función se bloquea hasta recibir la respuesta o
hasta que se venza el período de TimeOut especificado.

*)

(*Post_MemoAdd. (envío asíncrono) Manda el string "mensaje" al topo destino. Esta función es para test de la
comunicación.

En respuesta a este envio, el topo destino envía un mensaje MSGR_TOPO_MEMO_ADD
confirmando así que el mensaje fue recibido.
Si el envío tiene éxito se retorna el idPeticion que identifica el comunicado
enviado dentro de la librería nettopos local. Este identificador sirve a los
efectos de depuración del código.
Si hay error retorna 0 (cero).
*)
function post_MemoAdd( idNodoDestino: cardinal; mensaje: string ): integer;

(*Call_MemoAdd. (envío síncrono) Manda el string "mensaje" al topo destino. Esta función es para test de la
comunicación.

Si hay error retorna 0 (cero) en caso contrario un idComRespuesta > 0 (solo para debug)
*)
function call_MemoAdd( idNodoDestino: cardinal; mensaje: string; timeOut_ms: cardinal ): integer;




implementation

var
  idTarea: cardinal;
  idNodoLocal: Cardinal;
  idTopoLocal: Cardinal;


function getNextIdTarea: cardinal;
begin
 inc( idTarea );
 result:= idTarea;
end;

function post_MemoAdd( idNodoDestino: cardinal; mensaje: string ): integer;
var
  fc: TFichaComunicado;
  idPet: Cardinal;

begin
  if idAplic = 0 then raise Exception.Create('unettoposclientutils.Send_MemoAdd ; idAplic = 0 ' );
  fc.idNodoOrigen:= getIdNodoLocal;
  fc.idOrigen:= idAplic;
  fc.idNodoDestino:= idNodoDestino;
  fc.idDestino:= 0;
  fc.codigoMsg:= MSGP_TOPO_MEMO_ADD;
  fc.idTarea:= getNextIdTarea;
  fc.nBytesDatos:= length( mensaje );
  idPet:= comunicar( @fc, @mensaje[1], 5000 );
  result:= idPet;
end;


function call_MemoAdd( idNodoDestino: cardinal; mensaje: string; timeOut_ms: cardinal ): integer;
var
  fc, fcr: TFichaComunicado;
  idComRespuesta: Cardinal;

begin
  if idAplic = 0 then raise Exception.Create('unettoposclientutils.Send_MemoAdd ; idAplic = 0 ' );
  fc.idNodoOrigen:= 0;
  fc.idOrigen:= idAplic;
  fc.idNodoDestino:= idNodoDestino;
  fc.idDestino:= 0;

  fc.codigoMsg:= MSGP_TOPO_MEMO_ADD;
  fc.idTarea:= getNextIdTarea;
  fc.nBytesDatos:= length( mensaje );
  idComRespuesta:= comunicarTS( @fc, @mensaje[1], timeOut_ms );

  if leerFichaComunicado ( idComRespuesta, @fcr ) > 0 then
  begin
    levantarDatosComunicado( idComRespuesta, nil, 0 );
    result:= idComRespuesta;
  end
  else
  begin
    writeln(' OJO falló al leer la respuesta. ');
    result:= 0;
  end;

end;




function AlInicio( xNombreAplic: string; xidAplic: cardinal ): boolean;
begin
  unettopos.inicializar;
  idTarea:= 0;
  idAplic:= unettopos.registrarAplicacion( PChar(xNombreAplic), xidAplic);
  nombreAplic:= xNombreAplic;

  idNodoLocal:= getIdNodoLocal;
  idTopoLocal:= getIdAplicacion(0, uconstantes_nettopos.AppName_Topo );

  result:= idAplic = xidAplic;
end;

procedure AlFinal;
begin
   if idAplic > 0 then
  begin
    unettopos.desregistrarAplicacion( idAplic );
  end;
  unettopos.Finalizar;
end;

function IIE_NodosRegistrados: TDAOfNCardinal;
var
  fc_s, fc_e: TFichaComunicado;
  idComunicado: Cardinal;
  dato: TBuffReader;
  nodos: TDAofNCardinal;

begin

  fc_s.idNodoOrigen := 0;
  fc_s.idOrigen := idAplic;
  fc_s.idNodoDestino := 0;
  fc_s.idDestino := 0;
  fc_s.codigoMsg := MSGP_GETNODOS;
  fc_s.nBytesDatos := 0;

  idcomunicado := comunicarTS( @fc_s, nil, 5000 );

 if idcomunicado > 0 then
  begin
     if leerFichaComunicado(idComunicado, @fc_e) > 0 then
        begin
             if fc_e.nBytesDatos > 0 then
             begin
               dato := TBuffReader.Create( fc_e.pdatos, fc_e.nBytesDatos );
               dato.xTDAOfCardinal(nodos);
               levantarDatosComunicado ( idComunicado, nil, 0 );
               result := nodos;
             end
          else
          begin
            setlength( nodos, 0 );
            levantarDatosComunicado ( idComunicado, nil, 0 );
          end;
        end
     else
         writeln('Buffer llego vacio');
  end
  else
      writeln('Fallo comunicacion');
end;


end.

