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