Jump to content

diadoacbr

Problemas com comunicação TCP


jjw.roberto
Go to solution Solved by Daniel Simoes,
  • Este tópico foi criado há 2155 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Pessoal, bom dia.

Estou utilizando o ACBrMonitor compilado com Lazarus 1.6.

Durante a comunicação estou recebendo caracteres "extras" na resposta do ACBrMonitor Plus. 

Abaixo um exemplo do que está ocorrendo, mandei o comando "ECF.MFAdicional" e ele me retornou o seguinte abaixo. No exemplo abaixo existe:

- comando (ecf.mfadicional)

- resposta tratada como string

- resposta completa convertida em chars ansi.

ecf.mfadicional
[RESPOSTA] OK: ?
           #79 + #75 + #58 + #32 + #2 + #63 + #0 + #0 + #28 + #63 + #28 + #28 + #0 + #0 + #28 + #28 + #69 + #80 + #48 + #56 + #49 + #51 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #49 + #28 + #77 + #70 + #68 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #48 + #49 + #28 + #69 + #80 + #83 + #79 + #78 + #28 + #84 + #77 + #45 + #84 + #56 + #49 + #32 + #70 + #66 + #73 + #73 + #73 + #28 + #69 + #67 + #70 + #45 + #73 + #70 + #28 + #48 + #49 + #46 + #48 + #48 + #46 + #48 + #52 + #28 + #57 + #57 + #28 + #57 + #57 + #28 + #51 + #48 + #48 + #49 + #50 + #48 + #49 + #51 + #49 + #53 + #49 + #65 + #3

 

Depurando o ACBrMonitor Plus, no método de retorno de comando notei que o problema já aparece ali. Coloquei para logar o tamanho da string que será retornada no memo de log do monitorplus, e vejam:
 

Tamanho resposta: 112
ecf.mfadicional
OK: ?

Aqui o código que inseri no monitorplus (ACBrMonitor1.pas) marcado com o comentário "NOVO":

procedure TFrmACBrMonitor.Resposta(Comando, Resposta: ansistring);
var
  SL: TStringList;
begin
  if rbTCP.Checked then
  begin
    if Assigned(Conexao) then
    begin
      // >>>>> NOVO !!!!
      mResp.Lines.Add('Tamanho resposta: ' + inttostr(length(Resposta)));
      // <<<<<<<<<<<<<<<

      if chbTCPANSI.Checked then
        Resposta := Utf8ToAnsi(Resposta);

      Resposta := StringReplace(Resposta, chr(3), '', [rfReplaceAll]);
      Conexao.SendString(Resposta);
      Conexao.SendByte(3);

    end;
  end;

Alguém pode me ajudar para saber o que pode estar ocorrendo ?

Link to comment
Share on other sites

Pessoal, encontrei o "problema".

Na unit "DoECFUnit.pas" na procedure "procedure DoECF( Cmd: TACBrCmd );" existe um try-finally, aonde no finally existe esta situação:
 

	try
		// comandos do ECF
	finally
        if Length( Cmd.Resposta ) = 0 then
           Cmd.Resposta := RespostaComando ;
     end ;

Sendo assim, quando um comando (no caso o ECF.MFAdicional) é enviado e o retorno for "vazio", o ACBrMonitorPlus retorna a resposta da comunicação com a impressora ECF.

Qual o motivo disso? Não acham estranho (despadronizado) esse comportamento, pois toda vez que um parâmetro retornar vazio da ECF vai acabar retornando uma string bizarra que não tem nada haver com o valor da propriedade pedida?

Com base no que vi da implementação do ACBrMonitor Plus até agora, o certo deveria ser ter um comando para pegar essa informação quando necessário, por exemplo: "ECF.RespostaComando" (que inclusive já existe).

Edited by jjw.roberto
Link to comment
Share on other sites

O que estou dizendo é que, quando envio um comando por TCP para o ACBrMonitorPlus, como por exemplo o "ECF.MFAdicional", caso este comando retorne o valor vazio, o ACBrMonitorPlus está (no finally) retornando o valor do comando "ECF.ResponstaComando" (isso que estou relatando no 2º post). Isso irá acontecer para TODOS os comandos que retornarem o resultado com length = 0.

Se eu requisito um comando, e o valor dele é vazio, deveria retornar vazio e não o dado de outro comando que nem requisitei.

Resumindo, não é estranho pra vc, enviar um comando e receber o retorno de outro ? 

 

Edited by jjw.roberto
Link to comment
Share on other sites

  • 2 weeks later...
Em 16/09/2016 at 16:53, Daniel Simoes disse:

Preciso do Log do ACBrECF

Então Daniel, não é um problema na comunicação serial do ACBrECF, isso está funcionando maravilhosamente bem.

O que estou questionando é a comunicação TCP/IP que o ACBrMonitorPlus fornece, no qual permite que uma aplicação terceira envie comandos para o ACBrMonitorPlus manipular o ECF (um controle remoto do ECF por meio TCP).

A questão é a seguinte (pelo que existe na implementação do ACBrMonitorPlus):

- Todo o comando recebido pelo servidor TCP/IP no ACBrMonitorPlus, sempre que, retorne da ECF uma string vazia tem o comportamento retornar o "RespostaComando" do ACBrECF por padrão.

Por exemplo:

  • Envio ao ACBrMonitorPlus isso: "ECF.MFAdicional"
  • A impressora retorna ""
  • Neste momento, no finally da tratativa de comandos TCP do ACBrMonitorPlus, ele identifica que está retornando uma string vazia e reatribui o valor de retorno com o valor da propriedade "ACBrECF.RespostaComando"
    • Foi isso que citei nos primeiros POSTs à nível de fonte
    • É estranho eu mandar para o ACBrMonitorPlus "ECF.MFAdicional" e ele me retornar o valor do "ECF.RespostaComando"

Minha dúvida é esta, é uma questão de quebra do contrato da comunicação entre o ACBrMonitorPlus e a aplicação cliente.

Como vou saber se o retorno do comando é o valor que requisitei e não o valor RespostaComando?

Link to comment
Share on other sites

  • Fundadores
  • Solution

Obrigado pelo envio do Log e pela analise...

Suas informações estão corretas... e enviei ajuste no SVN baseado nas suas sugestões...

Eu precisava do Log para ter certeza de que o problema de retorno vazio do comando, não se tratava de um problema do ACBrECF

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link to comment
Share on other sites

Eu até arriscaria fazer uma sugestão de melhoria ao protocolo.

Tanto para envio como recebimento, poderia seguir a seguinte premissa:

[tamanho = 4 bytes] [byte1,byte2,byteN]

Assim, ao enviar o comando, você enviaria ao servidor primeiramente a quantidade de bytes do comando (length) e depois os bytes do comando em si. Para a resposta, fazer o mesmo, o integrador deve ler 4 bytes para saber o tamanho do buffer de retorno e então lê-lo.

 

Em uma visão mais técnica ficaria algo assim (programaticamente):

// exemplo do integrador/cliente fazendo a comunicação com o ACBrMonitorPlus via TCP

var cmd = "ECF.MFAdicional";
socket.writeInteger(length(cmd)); // 4 bytes do tamanho do comando (15)
socket.writeBuffer(cmd[1], length(cmd)); // 15 bytes do comando

var resultLen = socket.readInteger; // espera o servidor responder com 4 bytes contratando o tamanho do retorno
var result;
setLength(result, resultLen); // aloca o buffer para fazer a leitura do retorno
socket.readBuffer(result[1], resultLen); // faz a leitura dos bytes de retorno

// O servidor faz o inverso, aguarda sempre 4 bytes que representarão o tamanho do comando que irá receber, e depois lê o buffer, por exemplo:
var cmdLen = serverSocker.readInteger();
var cmd;
setLength(cmd, cmdLen);
serverSocker.readBuffer(cmd[1], cmdLen);
// cmd agora contém o comando recebido, no caso do exemplo acima seria "ECF.MFAdicional"

 

Os benefícios seriam:

  • possibilidade de enviar comandos com múltiplas linhas contendo CR+LF+ . + CR+LF (sequencia que atualmente denota ao servidor o término do comando enviado);
  • possibilidade de possuir o caracter ASCII #3 na resposta, que hoje por padrão é eliminado da resposta pois é utilizado como demarcador de término da resposta;
  • padronização do protocolo;
  • diminuição da quantidade de bytes no envio do comando (de 5 para 4, não que seja significativo)

 

Me prontifico à fazer a alteração e anexar um PATH caso tenham interesse.

 

Link to comment
Share on other sites

  • Fundadores

Acho que modificar o protocolo, pode atrapalhar muitas aplicações que já estão em produção...

Concordo que não é o protocolo ideal... mas ele foi idealizado para ser simples o bastante, para que a maioria dos programadores saibam como implementá-lo..

No inicio (ACBrMonitor), não tínhamos necessidade de comandos Longos, e contendo quebra de linhas... então usávamos LF como terminador... precisamos modificar isso, quando os (complexos) comandos da NFe chegaram... então adotamos o ETX...

Poderíamos aplicar um protocolo semelhante a de um ECF... com ACK após a recepção do comando enviado, e sua sintaxe verificada... Checksum dos dados,... tamanho dos pacotes (como vc sugeriu), etc... mas isso dificultaria muito a adesão de outras aplicações...

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link to comment
Share on other sites

  • Este tópico foi criado há 2155 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.