Ir para conteúdo
  • Cadastre-se

dev botao

Problemas com comunicação TCP


Ver Solução Respondido por Daniel Simoes,
  • Este tópico foi criado há 2984 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Postado

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 ?

Postado (editado)

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).

Editado por jjw.roberto
Postado

Não é um problema de ECF, como descrito no post.

É um problema de comportamento do ACBrMonitor Plus, referente ao protocolo de comunicação TCP.

Leia novamente os 2 primeiros Posts que você irá entender.

Postado (editado)

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 ? 

 

Editado por jjw.roberto
  • 2 semanas depois ...
Postado
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?

  • Fundadores
  • Solution
Postado

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.

Postado

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.

 

  • Fundadores
Postado

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.

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

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.