Ajuda Com componete TcpServer e TcpClient
Ola amigos, venho aqui pedir a ajuda de vcs mais uma vez,estou com dificuldades sobre esses compontes do titulo.
tenho uma lista de controladoras ,onde cada uma possue seu ip,essas controladoras contem leitores de codigos de barras e cartoes de aproximação,
consigo fazer a comunicação com uma contraladora só, usando os seguintes codigos
TCPClient = TCP
TCPServer = Server
Para configurar o TCPClient e o TCPServer
No onExecute to tCPServer
a funçao EnviaComando
e tem a funçao tratar o comando da controladora que e onde ela vai verificar os codigos de barras de acordo a a base de dados,tratando cada comando da controladora.
Sei que o TcpServer pode receber varios clientes. minhas controladoras estao gravadas em uma tabela, com o numero de ip de cada uma,como posso fazer a comunicaçao com todas elas ao mesmo tempo?para cada controladora irei precisar de um tcpclient? detalhe coloquei mais um tcpclient e configurei ele com outro ip de outra controladora,liguei as duas ao mesmo tempo,conectando elas a um switch,elas se comunicao porem quando eu passo o codigo de barras ela le mas manda o sinal para uma só como se as duas fossem o mesmo ip,se alguem puder me ajuda com um exemplo agradeço.
tenho uma lista de controladoras ,onde cada uma possue seu ip,essas controladoras contem leitores de codigos de barras e cartoes de aproximação,
consigo fazer a comunicação com uma contraladora só, usando os seguintes codigos
TCPClient = TCP
TCPServer = Server
Para configurar o TCPClient e o TCPServer
procedure TFrmGerenciador.conectar;
var
iValorConexao,I :integer;
Bindings : TIdSocketHandle;
begin
try
Screen.Cursor := -11;
TCP.Disconnect;
TCP.DisconnectNotifyPeer;
TCP.Host := '192.168.40.8';
TCP.Port := 9760;
Shape2.Pen.Color := clYellow;
SERVER.Active := false;
SERVER.Bindings.Clear;
Bindings := SERVER.Bindings.Add;
Bindings.IP := '0.0.0.0';
Bindings.Port := 9760;
SERVER.Active := true;
iValorConexao := 1;
TCP.Connect;
btnConectar.Enabled := true;
Screen.Cursor := 0;
Shape2.Pen.Color := cllime;
except on e:Exception do
begin
Screen.Cursor := 0;
btnConectar.Enabled := true;
Shape2.Pen.Color := clred;
SERVER.Active := false;
end;
end;
end;
No onExecute to tCPServer
procedure TFrmGerenciador.SERVERExecute(AContext: TIdContext);
var
byteBuf : TIdBytes;
Buffer : array [1..1024] of byte;
BufferSec : array [1..1024] of byte;
hexComado : string;
i : integer;
rx, tx : TRxTx;
tamStr : integer;
sComandoSec : string;
begin
try
FillChar(Buffer, SizeOf(Buffer), 0);
AContext.Connection.IOHandler.ReadBytes(byteBuf, 12, false);
idGlobal.BytesToRaw(byteBuf, Buffer, 12);
hexComado := '';
for i := 1 to 12 do
begin
hexComado := hexComado + IntToHex(Ord(Buffer[i]), 2);
end;
rx := strToRxTx(hexComado);
if(rx.tamanho > 0) then
begin
FillChar(BufferSec, SizeOf(BufferSec), 0);
AContext.Connection.IOHandler.ReadBytes(byteBuf, rx.tamanho + 1, false);
idGlobal.BytesToRaw(byteBuf, BufferSec, rx.tamanho + 1);
sComandoSec := '';
for i := 1 to rx.tamanho + 1 do
begin
sComandoSec := sComandoSec + IntToHex(Ord(BufferSec[i]), 2);
end;
rx.dados := RetZero(sComandoSec, 1024, false);
end;
tx := trataComandoPlaca(rx); // AQUI TRATA O COMANDO RECEBIDO DA CONTROLADORA
hexComado := RxTxtoStr(tx);
tamStr := length(hexComado) div 2;
FillChar(Buffer, SizeOf(Buffer), 0);
for i := 1 to tamStr do
begin
Buffer [i + 1] := HexToDec(hexComado[(i*2)+1] + hexComado[(i*2)+2]);
end;
byteBuf := Idglobal.RawToBytes(Buffer, tamStr);
AContext.Connection.IOHandler.Write(byteBuf);
except on e:Exception do
begin
AContext.Connection.DisconnectNotifyPeer;
end;
end;
end;
a funçao EnviaComando
function TFrmGerenciador.enviarComando(TX: TRxTx; resposta: Boolean): TRxTx;
var
hexComado, sComandoSec : WideString;
buf, rxBuf : array [1..1024] of byte;
bufSec : array [1..1024] of byte;
tamStr, i : integer;
rx : TRxTx;
byteBuf : TIdBytes;
begin
if(not tcp.Connected) then
begin
try
tcp.Connect();
except
exit;
end;
end;
if(not tcp.Connected) then
exit;
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
try
FillChar(buf, SizeOf(buf), 0);
// Comunicando := true;
//tx.chksum := calculaCK(tx);
hexComado := RxTxtoStr(tx);
tamStr := length(hexComado) div 2;
for i := 0 to tamStr - 1 do
begin
buf [i + 1] := HexToDec(hexComado[(i*2)+1] + hexComado[(i*2)+2]);
end;
if(tx.tamanho > 0) then
begin
byteBuf := Idglobal.RawToBytes(buf, 13 + tx.tamanho);
tcp.IOHandler.Write(byteBuf);
end
else
begin
byteBuf := Idglobal.RawToBytes(buf,12);
tcp.IOHandler.Write(byteBuf);
end;
if(resposta = true) then
begin
tcp.IOHandler.ReadTimeout := 2000;
tcp.IOHandler.ReadBytes(byteBuf, 12, false);
idGlobal.BytesToRaw(byteBuf, rxBuf, 12);
hexComado := '';
for i := 1 to 12 do
begin
hexComado := hexComado + IntToHex(Ord(rxBuf[i]), 2);
end;
rx := strToRxTx(hexComado);
rx.id_fonte := 0;
if(rx.tamanho > 0) then
begin
FillChar(bufSec, SizeOf(bufSec), 0);
tcp.IOHandler.ReadTimeout := 2000;
tcp.IOHandler.ReadBytes(byteBuf, rx.tamanho +1, false);
idGlobal.BytesToRaw(byteBuf, bufSec, rx.tamanho +1);
sComandoSec := '';
for i := 1 to rx.tamanho +1 do
begin
sComandoSec := sComandoSec + IntToHex(Ord(bufSec[i]), 2);
end;
rx.dados := RetZero(sComandoSec, 1024, false);
end;
Result := rx;
end;
// Comunicando := false;
except on e:Exception do
begin
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
Result := rx;
tcp.Disconnect;
end;
end;
end;
e tem a funçao tratar o comando da controladora que e onde ela vai verificar os codigos de barras de acordo a a base de dados,tratando cada comando da controladora.
Sei que o TcpServer pode receber varios clientes. minhas controladoras estao gravadas em uma tabela, com o numero de ip de cada uma,como posso fazer a comunicaçao com todas elas ao mesmo tempo?para cada controladora irei precisar de um tcpclient? detalhe coloquei mais um tcpclient e configurei ele com outro ip de outra controladora,liguei as duas ao mesmo tempo,conectando elas a um switch,elas se comunicao porem quando eu passo o codigo de barras ela le mas manda o sinal para uma só como se as duas fossem o mesmo ip,se alguem puder me ajuda com um exemplo agradeço.
Alan
Curtidas 0
Melhor post
Arthur Heinrich
19/02/2024
Se você conecta às controladoras, para enviar comandos e receber respostas, a sua controladora possui internamente um TCPServer. Você não precisa deste componente.
O que você precisa é de múltiplos TCPClient, um para cada controladora.
Você pode criar um array, instanciar cada elemento dinamicamente e acessar todos usando um "for", por exemplo.
O que você precisa é de múltiplos TCPClient, um para cada controladora.
Você pode criar um array, instanciar cada elemento dinamicamente e acessar todos usando um "for", por exemplo.
GOSTEI 1
Mais Respostas
Alan
18/02/2024
Se você conecta às controladoras, para enviar comandos e receber respostas, a sua controladora possui internamente um TCPServer. Você não precisa deste componente.
O que você precisa é de múltiplos TCPClient, um para cada controladora.
Você pode criar um array, instanciar cada elemento dinamicamente e acessar todos usando um "for", por exemplo.
O que você precisa é de múltiplos TCPClient, um para cada controladora.
Você pode criar um array, instanciar cada elemento dinamicamente e acessar todos usando um "for", por exemplo.
Arthur se não for pedir muito,poderia me dar um exemplo,para estudar?
Tenho um array
Minhas controladoras vão do IP 192.168.40.1 ao 192.168.40.99
IPS : array[1..99] of strings;
GOSTEI 0
Arthur Heinrich
18/02/2024
Ao invés de arrastar o componente para o seu Form e definir as propriedades em tempo de desenvolvimento, você precisa fazer isso dinamicamente.
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
var
sockets : array[1..99] of TTCPClient;
...
for i:=1 to 99 do
begin
sockets[i]:=TTCPClient.Create;
sockets[i].Host := IPS[i];
sockets[i].Port := 9760;
sockets[i].open;
end;
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
GOSTEI 1
Alan
18/02/2024
Ao invés de arrastar o componente para o seu Form e definir as propriedades em tempo de desenvolvimento, você precisa fazer isso dinamicamente.
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
var
sockets : array[1..99] of TTCPClient;
...
for i:=1 to 99 do
begin
sockets[i]:=TTCPClient.Create;
sockets[i].Host := IPS[i];
sockets[i].Port := 9760;
sockets[i].open;
end;
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
Arthur coloquei esse codigo no botão de conectar do meu form,ele ciar o tcpclient faz a conexão,mas nao tem resposta nenhuma , então fiz ele na funçao EnviarComando ,Criou os sockets TcpClient fez a comunicação mas ele manda a resposta para todas as controladoras conectadas,nao estou sabendo ler em uma controladora e enviar a resposta só pra ela.Criei uma lista de strings so com duas controladoras para testar pq se faço o for com as 99 e alguma nao tiver conectada, nao conecta nenhuma, então fiz com duas so , o codigo ficou assim:
function TFrmGerenciador.enviarComando(TX: TRxTx; resposta: Boolean): TRxTx;
var
hexComado, sComandoSec : WideString;
buf, rxBuf : array [1..1024] of byte;
bufSec : array [1..1024] of byte;
tamStr, i,M : integer;
rx : TRxTx;
byteBuf : TIdBytes;
begin
for m := 1 to 2 do
begin
sockets[m] :=TidTCPClient.Create;
sockets[M].Disconnect;
sockets[M].DisconnectNotifyPeer;
sockets[M].Host := ListaDeIps.Strings[m];
sockets[M].Port := 9760;
sockets[M].ConnectTimeout := -1;
sockets[M].IPVersion := Id_IPv4;
sockets[M].ReadTimeout := -1;
sockets[M].ReuseSocket := rsFalse;
sockets[M].Connect;
if(not sockets[m].Connected) then
//if(not tcp.Connected) then
begin
try
sockets[m].connect();
//tcp.Connect();
except
exit;
end;
end;
if(not sockets[m].Connected) then
//if(not tcp.Connected) then
exit;
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
try
FillChar(buf, SizeOf(buf), 0);
// Comunicando := true;
//tx.chksum := calculaCK(tx);
hexComado := RxTxtoStr(tx);
tamStr := length(hexComado) div 2;
for i := 0 to tamStr - 1 do
begin
buf [i + 1] := HexToDec(hexComado[(i*2)+1] + hexComado[(i*2)+2]);
end;
if(tx.tamanho > 0) then
begin
byteBuf := Idglobal.RawToBytes(buf, 13 + tx.tamanho);
//tcp.IOHandler.Write(byteBuf);
Sockets[m].IOHandler.Write(byteBuf);
end
else
begin
byteBuf := Idglobal.RawToBytes(buf,12);
// tcp.IOHandler.Write(byteBuf);
Sockets[m].IOHandler.Write(byteBuf);
end;
if(resposta = true) then
begin
//tcp.IOHandler.ReadTimeout := 2000;
//tcp.IOHandler.ReadBytes(byteBuf, 12, false);
Sockets[m].IOHandler.ReadTimeout := 2000;
Sockets[m].IOHandler.ReadBytes(byteBuf, 12, false);
idGlobal.BytesToRaw(byteBuf, rxBuf, 12);
hexComado := '';
for i := 1 to 12 do
begin
hexComado := hexComado + IntToHex(Ord(rxBuf[i]), 2);
end;
rx := strToRxTx(hexComado);
rx.id_fonte := 0;
if(rx.tamanho > 0) then
begin
FillChar(bufSec, SizeOf(bufSec), 0);
// tcp.IOHandler.ReadTimeout := 2000;
//tcp.IOHandler.ReadBytes(byteBuf, rx.tamanho +1, false);
Sockets[m].IOHandler.ReadTimeout := 2000;
Sockets[m].IOHandler.ReadBytes(byteBuf, rx.tamanho +1, false);
idGlobal.BytesToRaw(byteBuf, bufSec, rx.tamanho +1);
sComandoSec := '';
for i := 1 to rx.tamanho +1 do
begin
sComandoSec := sComandoSec + IntToHex(Ord(bufSec[i]), 2);
end;
rx.dados := RetZero(sComandoSec, 1024, false);
end;
Result := rx;
end;
except on e:Exception do
begin
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
Result := rx;
//tcp.Disconnect;
Sockets[m].Disconnect;
end;
end;
end;
end;
GOSTEI 0
Alan
18/02/2024
Ao invés de arrastar o componente para o seu Form e definir as propriedades em tempo de desenvolvimento, você precisa fazer isso dinamicamente.
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
var
sockets : array[1..99] of TTCPClient;
...
for i:=1 to 99 do
begin
sockets[i]:=TTCPClient.Create;
sockets[i].Host := IPS[i];
sockets[i].Port := 9760;
sockets[i].open;
end;
Você terá um array contendo 99 componentes TCPClient, cada um conectado ao IP de uma controladora. Tudo deve ser definido da mesma forma como você fez com a classe TCP, que arrastou para o seu form. Mas, neste contexto, será feito para a classe sockets[i].
Ao sair do programa, você pode encerrar a conexão de todos os sockets, com outro loop.
Sempre que um evento ocorre, o método associado ao evento é chamado, passando como parâmetro "Sender" a classe que deu origem ao evento.
Você deve utilizar este parâmetro para interagir com a controladora corretamente.
Arthur coloquei esse codigo no botão de conectar do meu form,ele ciar o tcpclient faz a conexão,mas nao tem resposta nenhuma , então fiz ele na funçao EnviarComando ,Criou os sockets TcpClient fez a comunicação mas ele manda a resposta para todas as controladoras conectadas,nao estou sabendo ler em uma controladora e enviar a resposta só pra ela.Criei uma lista de strings so com duas controladoras para testar pq se faço o for com as 99 e alguma nao tiver conectada, nao conecta nenhuma, então fiz com duas so , o codigo ficou assim:
function TFrmGerenciador.enviarComando(TX: TRxTx; resposta: Boolean): TRxTx;
var
hexComado, sComandoSec : WideString;
buf, rxBuf : array [1..1024] of byte;
bufSec : array [1..1024] of byte;
tamStr, i,M : integer;
rx : TRxTx;
byteBuf : TIdBytes;
begin
for m := 1 to 2 do
begin
sockets[m] :=TidTCPClient.Create;
sockets[M].Disconnect;
sockets[M].DisconnectNotifyPeer;
sockets[M].Host := ListaDeIps.Strings[m];
sockets[M].Port := 9760;
sockets[M].ConnectTimeout := -1;
sockets[M].IPVersion := Id_IPv4;
sockets[M].ReadTimeout := -1;
sockets[M].ReuseSocket := rsFalse;
sockets[M].Connect;
if(not sockets[m].Connected) then
//if(not tcp.Connected) then
begin
try
sockets[m].connect();
//tcp.Connect();
except
exit;
end;
end;
if(not sockets[m].Connected) then
//if(not tcp.Connected) then
exit;
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
try
FillChar(buf, SizeOf(buf), 0);
// Comunicando := true;
//tx.chksum := calculaCK(tx);
hexComado := RxTxtoStr(tx);
tamStr := length(hexComado) div 2;
for i := 0 to tamStr - 1 do
begin
buf [i + 1] := HexToDec(hexComado[(i*2)+1] + hexComado[(i*2)+2]);
end;
if(tx.tamanho > 0) then
begin
byteBuf := Idglobal.RawToBytes(buf, 13 + tx.tamanho);
//tcp.IOHandler.Write(byteBuf);
Sockets[m].IOHandler.Write(byteBuf);
end
else
begin
byteBuf := Idglobal.RawToBytes(buf,12);
// tcp.IOHandler.Write(byteBuf);
Sockets[m].IOHandler.Write(byteBuf);
end;
if(resposta = true) then
begin
//tcp.IOHandler.ReadTimeout := 2000;
//tcp.IOHandler.ReadBytes(byteBuf, 12, false);
Sockets[m].IOHandler.ReadTimeout := 2000;
Sockets[m].IOHandler.ReadBytes(byteBuf, 12, false);
idGlobal.BytesToRaw(byteBuf, rxBuf, 12);
hexComado := '';
for i := 1 to 12 do
begin
hexComado := hexComado + IntToHex(Ord(rxBuf[i]), 2);
end;
rx := strToRxTx(hexComado);
rx.id_fonte := 0;
if(rx.tamanho > 0) then
begin
FillChar(bufSec, SizeOf(bufSec), 0);
// tcp.IOHandler.ReadTimeout := 2000;
//tcp.IOHandler.ReadBytes(byteBuf, rx.tamanho +1, false);
Sockets[m].IOHandler.ReadTimeout := 2000;
Sockets[m].IOHandler.ReadBytes(byteBuf, rx.tamanho +1, false);
idGlobal.BytesToRaw(byteBuf, bufSec, rx.tamanho +1);
sComandoSec := '';
for i := 1 to rx.tamanho +1 do
begin
sComandoSec := sComandoSec + IntToHex(Ord(bufSec[i]), 2);
end;
rx.dados := RetZero(sComandoSec, 1024, false);
end;
Result := rx;
end;
except on e:Exception do
begin
rx.stx := 0;
rx.tamanho := 0;
rx.id_destino := 0;
rx.id_sub_destino := 0;
rx.id_fonte := 0;
rx.comando := '0000';
rx.dados := '';
rx.chksum := 0;
rx.etx := 0;
Result := rx;
//tcp.Disconnect;
Sockets[m].Disconnect;
end;
end;
end;
end;
Tenho uma função que trata o comando recebido pela controladora, nele fiz um case dos comandos ,ficou mais ou menos assim,dei uma abreviada para não ficar muito grande o codigo.
function TFrmGerenciador.trataComandoPlaca(RX: TRxTx): TRxTx; /////
var
rxStr : string;
receber :shortString;
comando : string;
tx : TRxTx;
i, n,j : Integer;
sTemplate : WideString;
sTemplate2: WideString;
buf : array of Byte;
card64 : Cardinal;
Mifare : String;
strSerial: String;
txx, rxx : TRxTx;
sTemp, sTemp2, sComando: string;
num_bytes,l :Integer;
begin
try
tx.stx := 2;
tx.chksum := 0;
tx.comando := '0101';
tx.dados := RetZero('', 1024, true);
tx.etx := 3;
tx.id_destino :=0;
tx.id_fonte := 0;
tx.id_sub_destino := 0;
tx.tamanho := 0;
//verifica ck
rxStr := RxTxtoStr(RX);
comando := RX.comando;
// card64 := HexToCardinal(InverteHexa(Copy (rx.dados,3,8), 8));
//id := HexToDec(Copy (rx.dados,1,2));
card64 := HexToCardinal(InverteHexa(Copy ( rx.dados,1,8), 8));
if(HexToDEC(comando) = $0000)then
begin
tx.comando := '0102';
Result := tx;
exit;
end;
case HexToDEC(comando) of
$0701: begin // LEITOR DE APROXIMAÇÃO.
// VERIFICO SE O REGISTRO EXISTE NA TABELA COM AS CONDIÇÕES "IF"
SE O NUMERO DO INGRESSO EXISTE NA TABELA, SALVA EM OUTRA TABELA E MANDA MENSAGEM PARA O DISPLAY DA CONTROLADORA
// MANDA MENSAGEM PARA O DISPLAY
sTemp := '';
sTemp2 := '';
sComando := '';
sTemp := ' >> ENTRADA << ';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
sTemp := '>> PERMITIDA <<';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
SComando := SComando + IntToHex(StrToInt('10'), 2);
// AQUI FAZ A LIBERAÇÃO NA CONTROLADORA MANDANDO O COMANDO
tx.stx := 2;
tx.chksum := 0;
tx.comando := '080F' ;// COMANDO PARA MANDAR MENSAGEM PARA ACONTROLADORA
tx.dados := RetZero(SComando, 512, false);
tx.etx := 3;
tx.id_destino := 1;
tx.id_fonte := 9;
tx.id_sub_destino := 8;
tx.tamanho := length(SComando) div 2;
rx := enviarComando(tx, true);
// LIBERA O ACESSO.
tx.stx := 2;
tx.chksum := 0;
tx.comando := '080B' ; //COMANDO DE LIBERAÇÃO
tx.dados := RetZero(SComando, 512, false);
tx.etx := 3;
tx.id_destino := 1;
tx.id_fonte := 9;
tx.id_sub_destino := 8;
tx.tamanho := length(SComando) div 2;
rx := enviarComando(tx, true);
end;
GOSTEI 0
Alan
18/02/2024
//VERIFICA SE O INGRESSO JÁ FOI ULTILIZADO,SE SIM BLOQUEIA E MANDA MENSAGEM PARA A CONTROLADORA E SALVA NA TABELA
//MENSAGEM QUE VAI ENVIAR PARA A CONTROLADORA
sTemp := '';
sTemp2 := '';
sComando := '';
sTemp := '>>JA UTILIZADO<<';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
sTemp := dateTimeToStr(dm.IngressosTabledata_entrou.value);
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
SComando := SComando + IntToHex(StrToInt('10'), 2);
tx.stx := 2;
tx.chksum := 0;
tx.comando := '080F'; //COMANDO PARA MANDAR MENSAGEM PARA ACONTROLADORA
tx.dados := RetZero(SComando, 512, false);
tx.etx := 3;
tx.id_destino := 1;
tx.id_fonte := 9;
tx.id_sub_destino := 8;
tx.tamanho := length(SComando) div 2;
rx := enviarComando(tx, true);
end;
// VERIFICA SE O SETOR É PERMITIDO
if (dm.Ingressostable.RecordCount <> 0) and (dm.IngressosTablePermitido.value = 0) then
begin
//emensagem1.Text := INTTOSTR(CARD64);
dm.IngressosEvento.Open;
dm.IngressosEvento.Append;
dm.IngressosEventoIdentificacao.value := IntToStr(card64);
dm.IngressosEventoDescricao.Value := 'SETOR INCORRETO';
dm.IngressosEventoTipo.Value := 'BLOQUEIO';
dm.IngressosEventoId_setor.Value := dm.IngressosTableId_setor.Value;
dm.IngressosEventoid_ingresso.Value := dm.ingressostableid.value;
dm.IngressosEventoId_controladora.Value := rx.id_fonte;
dm.IngressosEvento.post;
sTemp := '';
sTemp2 := '';
sComando := '';
sTemp := 'SETOR INCORRETO';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
sTemp := dm.IngressosTableSetor.value;
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
SComando := SComando + IntToHex(StrToInt('10'), 2);
tx.stx := 2;
tx.chksum := 0;
tx.comando := '080F';
tx.dados := RetZero(SComando, 512, false);
tx.etx := 3;
tx.id_destino := 1;
tx.id_fonte := 9;
tx.id_sub_destino := 8;
tx.tamanho := length(SComando) div 2;
rx := enviarComando(tx, true);
end;
//VERIFICO SE O INGRESSO EXISTE, SE NAO ,SALVA NA TABELA E MANDA A MENSSAGEM
sTemp := '';
sTemp2 := '';
sComando := '';
sTemp := '>>INGRESSO NAO<<';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
sTemp := '>>>CADASTRADO<<<';
num_bytes := length(sTemp);
sTemp2 := '';
for l := 1 to num_bytes do
begin
sTemp2 := sTemp2 + CharStrToHexStr(sTemp[l]);
end;
SComando := SComando + RetZero(sTemp2, 32, false);
SComando := SComando + IntToHex(StrToInt('10'), 2);
tx.stx := 2;
tx.chksum := 0;
tx.comando := '080F'; COMANDO PARA MANDAR MENSAGEM PARA ACONTROLADORA
tx.dados := RetZero(SComando, 512, false);
tx.etx := 3;
tx.id_destino := 1;
tx.id_fonte := 9;
tx.id_sub_destino := 8;
tx.tamanho := length(SComando) div 2;
rx := enviarComando(tx, true);
end;
end;
end;
$0A01 : begin // COMANDO QUANDO RODA O BRAÇO DA CATRACA (CONTROLADORA)
// SALVA O REGISTRO NA TABELA, FAZ UM UPDATE PARA O INGRESSO NAO SER MAIS VALIDO.
dm.Ingressostable.Open;
dm.Ingressostable.Filtered := false;
dm.Ingressostable.Filter := 'identificacao =' + IDENTIFIC;
dm.Ingressostable.Filtered := true;
if dm.Ingressostable.RecordCount > 0 then
if (Dm.IngressosTablehexadecimal.Value = 0) then
begin
dm.IngressosEvento.Open;
dm.IngressosEvento.Append;
dm.IngressosEventoId_controladora.Value := rx.id_fonte;
dm.IngressosEventoId_setor.Value := dm.IngressosTableId_setor.Value;
dm.IngressosEventoId_ingresso.Value := dm.IngressosTableid.AsInteger;
dm.IngressosEventoIdentificacao.Value := IDENTIFIC;
dm.IngressosEventoDescricao.Value := 'ENTRADA CONCLUIDA';
dm.IngressosEventoTipo.value := 'ENTRADA';
dm.IngressosEvento.Post;
//FAZ UM UPDATE PARA DESVALIDAR.
dm.IngressosTable.sql.Clear;
dm.IngressosTable.SQL.Add('update ingressos SET Valido = "1" WHERE Valido = "0" AND Identificacao = :pident');
dm.IngressosTable.ParamByName('pident').value := IDENTIFIC;;
Dm.IngressosTable.ExecSQL;
// ABRE A TABELA DE INGRESSOS
dm.IngressosTable.close;
dm.IngressosTable.SQL.Clear;
dm.IngressosTable.SQL.Add('select *from ingressos') ;
dm.IngressosTable.open;
end;
END;
$0A31 : begin //COMANDO QUANDO O BRAÇO DA CATRACA(CONTROLADORA )NAO E RODADO
//SÓ INSERE NA TABELA
dm.IngressosEvento.Open;
dm.IngressosEvento.Append;
dm.IngressosEventoId_setor.Value := dm.IngressosTableId_setor.Value;
dm.IngressosEventoId_controladora.Value := rx.id_fonte;
dm.IngressosEventoId_ingresso.Value := dm.IngressosTableid.AsInteger;
dm.IngressosEventoIdentificacao.Value := IDENTIFIC;
dm.IngressosEventoDescricao.Value := 'ENTRADA NÃO CONCLUÍDA';
dm.IngressosEventoTipo.value :='NENHUM';
dm.IngressosEvento.Post;
end;
end;
o rx.id_fonte é o id da placa , nao sei se estou errando algo aqui
GOSTEI 0
Arthur Heinrich
18/02/2024
Você está pensando de forma síncrona, onde envia um comando e aguarda pela resposta. Comunicações de rede funcionam melhor quando utilizamos uma lógica assíncrona, onde você envia um comando e, eventualmente e em algum momento, a resposta chega, podendo não chegar. Enquanto isso, seu programa segue fazendo outras atividades, até que uma mensagem chegue de uma das interfaces. Neste momento, seu código será interrompido para tratar a mensagem recebida.
Um componente do tipo TCPSocket possui eventos (event handlers), que precisam ser implementados e associados à classe, no momento da criação/conexão. Como exemplo, seguem os eventos da classe TClientSocket:
OnConnect: Occurs on client sockets just after the connection to the server is opened.
OnConnecting: Occurs for a client socket after the server socket has been located, but before the connection is established.
OnDisconnect: Occurs just before a client socket closes the connection to a server socket.
OnError: Occurs when the socket fails in making, using, or shutting down a connection.
OnLookup: Occurs when a client socket is about to look up the server socket with which it wants to connect.
OnRead: Occurs when a client socket should read information from the socket connection.
OnWrite: Occurs when a client socket should write information to the socket connection.
Sempre que o server envia uma resposta, o evento OnRead é disparado, para que você trate a mensagem recebida de um socket em particular.
No link https://stackoverflow.com/questions/25733064/error-with-sockets-in-delphi existe um exemplo, onde são criados e atribuídos os event handlers.
A procedure/método usado para ler os dados do socket (no exemplo) é esta:
Repare que, ao ler os dados, ele utiliza o socket passado para o event handler (parâmetro Socket). Este é o socket que recebeu a mensagem e é a partir desta classe que você precisa ler os dados. Você não precisa adivinhar qual dos sockets que você mantém no array está interagindo com você.
É importante lembrar que, quando um pacote de rede chega, ele pode conter dados parciais. Você precisa de um mecanismo para tratar os dados recebidos e perceber se chegaram múltiplas mensagens ou se a última/única mensagem que chegou está completa.
Isto tem a ver com o protocolo utilizado pela aplicação ou, no seu caso, as suas interfaces.
A beleza da orientação a objetos é justamente o fato de você poder criar uma classe a partir de outra. Você pode criar uma classe sua TInterfaceSocket, que herde as características do socket padrão, implementando os eventos (event handlers internamente), no evento OnCreate ou através do Constructor, de forma que cada classe se comporte como um pequeno programa, que interage com apenas uma interface. Nela, pode haver um buffer onde você vai concatenando os dados recebidos e, à medida que uma resposta chega completa, você a trata e descarta do buffer a parte já tratada.
Ao adotar a abordagem orientada a objetos, você torna seu problema mais simples.
Um componente do tipo TCPSocket possui eventos (event handlers), que precisam ser implementados e associados à classe, no momento da criação/conexão. Como exemplo, seguem os eventos da classe TClientSocket:
OnConnect: Occurs on client sockets just after the connection to the server is opened.
OnConnecting: Occurs for a client socket after the server socket has been located, but before the connection is established.
OnDisconnect: Occurs just before a client socket closes the connection to a server socket.
OnError: Occurs when the socket fails in making, using, or shutting down a connection.
OnLookup: Occurs when a client socket is about to look up the server socket with which it wants to connect.
OnRead: Occurs when a client socket should read information from the socket connection.
OnWrite: Occurs when a client socket should write information to the socket connection.
Sempre que o server envia uma resposta, o evento OnRead é disparado, para que você trate a mensagem recebida de um socket em particular.
No link https://stackoverflow.com/questions/25733064/error-with-sockets-in-delphi existe um exemplo, onde são criados e atribuídos os event handlers.
A procedure/método usado para ler os dados do socket (no exemplo) é esta:
procedure ClientRead(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
var
len: Integer;
Buf: PByte;
begin
len := Socket.ReceiveLength;
if len <= 0 then Exit;
GetMem(Buf, len);
try
len := Socket.ReceiveBuf(Buf^, len);
if len <= 0 then Exit;
// use data as needed...
finally
FreeMem(Buf);
end;
end;
Repare que, ao ler os dados, ele utiliza o socket passado para o event handler (parâmetro Socket). Este é o socket que recebeu a mensagem e é a partir desta classe que você precisa ler os dados. Você não precisa adivinhar qual dos sockets que você mantém no array está interagindo com você.
É importante lembrar que, quando um pacote de rede chega, ele pode conter dados parciais. Você precisa de um mecanismo para tratar os dados recebidos e perceber se chegaram múltiplas mensagens ou se a última/única mensagem que chegou está completa.
Isto tem a ver com o protocolo utilizado pela aplicação ou, no seu caso, as suas interfaces.
A beleza da orientação a objetos é justamente o fato de você poder criar uma classe a partir de outra. Você pode criar uma classe sua TInterfaceSocket, que herde as características do socket padrão, implementando os eventos (event handlers internamente), no evento OnCreate ou através do Constructor, de forma que cada classe se comporte como um pequeno programa, que interage com apenas uma interface. Nela, pode haver um buffer onde você vai concatenando os dados recebidos e, à medida que uma resposta chega completa, você a trata e descarta do buffer a parte já tratada.
Ao adotar a abordagem orientada a objetos, você torna seu problema mais simples.
GOSTEI 1
Alan
18/02/2024
Você está pensando de forma síncrona, onde envia um comando e aguarda pela resposta. Comunicações de rede funcionam melhor quando utilizamos uma lógica assíncrona, onde você envia um comando e, eventualmente e em algum momento, a resposta chega, podendo não chegar. Enquanto isso, seu programa segue fazendo outras atividades, até que uma mensagem chegue de uma das interfaces. Neste momento, seu código será interrompido para tratar a mensagem recebida.
Um componente do tipo TCPSocket possui eventos (event handlers), que precisam ser implementados e associados à classe, no momento da criação/conexão. Como exemplo, seguem os eventos da classe TClientSocket:
OnConnect: Occurs on client sockets just after the connection to the server is opened.
OnConnecting: Occurs for a client socket after the server socket has been located, but before the connection is established.
OnDisconnect: Occurs just before a client socket closes the connection to a server socket.
OnError: Occurs when the socket fails in making, using, or shutting down a connection.
OnLookup: Occurs when a client socket is about to look up the server socket with which it wants to connect.
OnRead: Occurs when a client socket should read information from the socket connection.
OnWrite: Occurs when a client socket should write information to the socket connection.
Sempre que o server envia uma resposta, o evento OnRead é disparado, para que você trate a mensagem recebida de um socket em particular.
No link https://stackoverflow.com/questions/25733064/error-with-sockets-in-delphi existe um exemplo, onde são criados e atribuídos os event handlers.
A procedure/método usado para ler os dados do socket (no exemplo) é esta:
Repare que, ao ler os dados, ele utiliza o socket passado para o event handler (parâmetro Socket). Este é o socket que recebeu a mensagem e é a partir desta classe que você precisa ler os dados. Você não precisa adivinhar qual dos sockets que você mantém no array está interagindo com você.
É importante lembrar que, quando um pacote de rede chega, ele pode conter dados parciais. Você precisa de um mecanismo para tratar os dados recebidos e perceber se chegaram múltiplas mensagens ou se a última/única mensagem que chegou está completa.
Isto tem a ver com o protocolo utilizado pela aplicação ou, no seu caso, as suas interfaces.
A beleza da orientação a objetos é justamente o fato de você poder criar uma classe a partir de outra. Você pode criar uma classe sua TInterfaceSocket, que herde as características do socket padrão, implementando os eventos (event handlers internamente), no evento OnCreate ou através do Constructor, de forma que cada classe se comporte como um pequeno programa, que interage com apenas uma interface. Nela, pode haver um buffer onde você vai concatenando os dados recebidos e, à medida que uma resposta chega completa, você a trata e descarta do buffer a parte já tratada.
Ao adotar a abordagem orientada a objetos, você torna seu problema mais simples.
Um componente do tipo TCPSocket possui eventos (event handlers), que precisam ser implementados e associados à classe, no momento da criação/conexão. Como exemplo, seguem os eventos da classe TClientSocket:
OnConnect: Occurs on client sockets just after the connection to the server is opened.
OnConnecting: Occurs for a client socket after the server socket has been located, but before the connection is established.
OnDisconnect: Occurs just before a client socket closes the connection to a server socket.
OnError: Occurs when the socket fails in making, using, or shutting down a connection.
OnLookup: Occurs when a client socket is about to look up the server socket with which it wants to connect.
OnRead: Occurs when a client socket should read information from the socket connection.
OnWrite: Occurs when a client socket should write information to the socket connection.
Sempre que o server envia uma resposta, o evento OnRead é disparado, para que você trate a mensagem recebida de um socket em particular.
No link https://stackoverflow.com/questions/25733064/error-with-sockets-in-delphi existe um exemplo, onde são criados e atribuídos os event handlers.
A procedure/método usado para ler os dados do socket (no exemplo) é esta:
procedure ClientRead(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
var
len: Integer;
Buf: PByte;
begin
len := Socket.ReceiveLength;
if len <= 0 then Exit;
GetMem(Buf, len);
try
len := Socket.ReceiveBuf(Buf^, len);
if len <= 0 then Exit;
// use data as needed...
finally
FreeMem(Buf);
end;
end;
Repare que, ao ler os dados, ele utiliza o socket passado para o event handler (parâmetro Socket). Este é o socket que recebeu a mensagem e é a partir desta classe que você precisa ler os dados. Você não precisa adivinhar qual dos sockets que você mantém no array está interagindo com você.
É importante lembrar que, quando um pacote de rede chega, ele pode conter dados parciais. Você precisa de um mecanismo para tratar os dados recebidos e perceber se chegaram múltiplas mensagens ou se a última/única mensagem que chegou está completa.
Isto tem a ver com o protocolo utilizado pela aplicação ou, no seu caso, as suas interfaces.
A beleza da orientação a objetos é justamente o fato de você poder criar uma classe a partir de outra. Você pode criar uma classe sua TInterfaceSocket, que herde as características do socket padrão, implementando os eventos (event handlers internamente), no evento OnCreate ou através do Constructor, de forma que cada classe se comporte como um pequeno programa, que interage com apenas uma interface. Nela, pode haver um buffer onde você vai concatenando os dados recebidos e, à medida que uma resposta chega completa, você a trata e descarta do buffer a parte já tratada.
Ao adotar a abordagem orientada a objetos, você torna seu problema mais simples.
Cara para falar a verdade estou quebrando a cabeça a dias com isso,esses codigos que te mandei é uns fontes que o fabricante da controladora me passou ,só dei uma modificada ,mas estou apanhando muito nesses componentes,para ser sincero ja nem sei mais se vou ser capaz de conseguir isso, minha ideia e levar ao maximo ate onde eu conseguir ,e depois ver se acho alguem para finalizar para mim.Voce disse que esta com muito serviço e nao tera atenção q um cliente precisa,tem alguma ideia de quando voce ficaria livre,ou tem algum contato pra me indicar,ou pode me indicar algum curso sobre esses componentes?
GOSTEI 0
Arthur Heinrich
18/02/2024
Eu trabalho full time dedicado para uma empresa e também não sou nenhum especialista em sockets.
Olhando as rotinas que você encaminhou, a comunicação ocorre em binário. A rorina fica convertendo os dados binários em hexadecimal e vice-versa. Tem várias classes que parecem ser do fornecedor das interfaces. É meio complicado. Tem que ler a documentação e implementar.
Dá trabalho mesmo.
Antes de implementar para todas as interfaces. Você precisa aprender a lidar com uma só, até entender como enviar comandos e receber a resposta. Somente depois de estar familiarizado com o protocolo e com as classes do fabricante é que você deve tentar tratar múltiplas interfaces ao mesmo tempo. Do contrário, você mistura duas coisas que não sabe fazer muito bem e ficará perdido, sem saber onde errou.
Olhando as rotinas que você encaminhou, a comunicação ocorre em binário. A rorina fica convertendo os dados binários em hexadecimal e vice-versa. Tem várias classes que parecem ser do fornecedor das interfaces. É meio complicado. Tem que ler a documentação e implementar.
Dá trabalho mesmo.
Antes de implementar para todas as interfaces. Você precisa aprender a lidar com uma só, até entender como enviar comandos e receber a resposta. Somente depois de estar familiarizado com o protocolo e com as classes do fabricante é que você deve tentar tratar múltiplas interfaces ao mesmo tempo. Do contrário, você mistura duas coisas que não sabe fazer muito bem e ficará perdido, sem saber onde errou.
GOSTEI 1
Alan
18/02/2024
Eu trabalho full time dedicado para uma empresa e também não sou nenhum especialista em sockets.
Olhando as rotinas que você encaminhou, a comunicação ocorre em binário. A rorina fica convertendo os dados binários em hexadecimal e vice-versa. Tem várias classes que parecem ser do fornecedor das interfaces. É meio complicado. Tem que ler a documentação e implementar.
Dá trabalho mesmo.
Antes de implementar para todas as interfaces. Você precisa aprender a lidar com uma só, até entender como enviar comandos e receber a resposta. Somente depois de estar familiarizado com o protocolo e com as classes do fabricante é que você deve tentar tratar múltiplas interfaces ao mesmo tempo. Do contrário, você mistura duas coisas que não sabe fazer muito bem e ficará perdido, sem saber onde errou.
É então com uma controladora só funciona perfeito,mas quando conecto mais de uma,não importa por qual controladora vc lê o ingresso ela manda mensagem para todas ,só pra salvar na tabela q ela salva com id certo de cada uma, mas vou fuçar mais um pouco e ver no que dá ,se não der em nada vou ter que procurar alguém que faça para mim ,mas uma vez obrigado.
Olhando as rotinas que você encaminhou, a comunicação ocorre em binário. A rorina fica convertendo os dados binários em hexadecimal e vice-versa. Tem várias classes que parecem ser do fornecedor das interfaces. É meio complicado. Tem que ler a documentação e implementar.
Dá trabalho mesmo.
Antes de implementar para todas as interfaces. Você precisa aprender a lidar com uma só, até entender como enviar comandos e receber a resposta. Somente depois de estar familiarizado com o protocolo e com as classes do fabricante é que você deve tentar tratar múltiplas interfaces ao mesmo tempo. Do contrário, você mistura duas coisas que não sabe fazer muito bem e ficará perdido, sem saber onde errou.
GOSTEI 0