ECF comunicação direta - Presentão

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

leandrolinauer
Usuário Nível 3
Usuário Nível 3
Mensagens: 413
Registrado em: 16 Out 2006 10:59
Localização: Paranaíba-MS

ECF comunicação direta - Presentão

Mensagem por leandrolinauer »

:))
Bom dia a todos.
Conforme prometido e promessa é dívida, vai aí abaixo o codigo do gerenciamento de ecf com xHarbour usando a HbComm para comunicação direta com impressoras fiscais.
Ps: Agradeço aqui a todos que me ajudaram neste empenho.
Demorei muito para mandar, devido a leitura dos retornos da impressora fiscal, não estava conseguindo obter resultados, mas agora já estou usando em térmica e em matricial BEMATECH.

ps: Se alguém tiver alguma idéia para melhorar a mais, sinta-se a vontade, mas peço-lhes que postem a melhoria no fórum.
:{

Código: Selecionar todos

/// fun‡oes gerais de ecfs (inicio)

Static Function IBE_PREP_BUFFER()  //    Calcula CheckSum de acordo com o  
//  protocolo da Impressora. Retorna String com o BUFFER para ser enviado 
Local iSoma,iConta,c_LENCMD,c_NBL,c_NBH,c_CSL,c_CSH,a_CMD
If !Empty(c_CMD)
   a_CMD   :=CHR(27) + c_CMD
   iSoma   :=SOMAASC( a_CMD )
   c_LENCMD:=Len( a_CMD ) + 2   // + 2 = CSL + CSH

   c_NBL   :=CHR( Mod ( c_LENCMD , 256) )
   c_NBH   :=CHR( Int ( c_LENCMD / 256) ) 
   c_CSL   :=CHR( Mod ( iSoma,  256 ) ) 
   c_CSH   :=CHR( Int ( iSoma / 256 ) )
   c_CMD   :=c_STX + c_NBL + c_NBH + a_CMD + c_CSL + c_CSH
EndIf
Return .T.
//*
Function SOMAASC(CMD)
a_SOMA:=0
For i:=1 To Len(CMD)
    a_SOMA:=a_SOMA+Asc(SubStr(CMD,i,1))
Next
Return a_SOMA
//*
Function IBE_BCD_ASC(DADOS)  // Converte String BCD para ASC
local RET := "",A,BH,BL,ASC_CHAR,BCD_CHAR
For A := 1 To Len( DADOS ) 
   BCD_CHAR :=ASC( SubStr( DADOS, A, 1 ) ) 
   BH       :=StrZero( Int( BCD_CHAR / 16 ), 1, 0 ) 
   BL       :=StrZero( Mod( BCD_CHAR,  16 ), 1, 0 ) 
   ASC_CHAR :=BH + BL 
   RET += ASC_CHAR 
Next
Return RET 

// Estas funções acima foi  ajuda que recebi do grupo, a minha tinha ficado mais extensa, heheh.
//********************************************************** 
Function ECF_DIRETA(a_CMD,a_TXT) //cria os comandos
Local lRet:=.F.
Private c_CMD:=""
Private c_TRD:=3 //Tamanho Retorno Dados em bytes num‚ricos
a_CMD:=UPPER(a_CMD)
a_TXT:=If(a_TXT=NIL,"",a_TXT)
/////////////transforma o cmd
If a_CMD=="ABRE CUPOM"
   If wECF_MODELO=="B"
      c_CMD:=CHR(0) //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="REDUCAO Z" 
   If wECF_MODELO=="B"
      c_CMD:=CHR(5) // correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="ABRE CAIXA"
   If wECF_MODELO=="B"
      c_CMD:=CHR(6) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="PDV" //retorna o numero do caixa
   If wECF_MODELO=="B"
      c_CMD:=CHR(35)+CHR(14) //correto
      c_TRD:=c_TRD+2
   EndIf
ElseIf a_CMD=="UNIDADE DE MEDIDA"
   If wECF_MODELO=="B"
      c_CMD:=CHR(62)+CHR(51) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="AUMENTA DESCRICAO"
   If wECF_MODELO=="B"
      c_CMD:=CHR(62)+CHR(52) //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="VENDA ITEM DECIMAIS 2"
   If wECF_MODELO=="B"
      c_CMD:=CHR(9)   //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="VENDA ITEM DECIMAIS 3"
   If wECF_MODELO=="B"
      c_CMD:=CHR(56) //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="VENDA ITEM DEPARTAMENTO"
   If wECF_MODELO=="B"
      c_CMD:=CHR(63)   //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="INICIA FECHAMENTO CUPOM"
   If wECF_MODELO=="B"
      c_CMD:=CHR(32)  //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="PROGRAMA FORMA PAGAMENTO"
   If wECF_MODELO=="B"
      c_CMD:=CHR(71) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="EFETUA FORMA PAGAMENTO"
   If wECF_MODELO=="B"
      c_CMD:=CHR(72) //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="PROGRAMA VARIAS FORMAS PAGAMENTO"
   If wECF_MODELO=="B"
      c_CMD:=CHR(73) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="FINALIZA FECHAMENTO CUPOM"
   If wECF_MODELO=="B"
      c_CMD:=CHR(34) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="LEITURA X"
   If wECF_MODELO=="B"
      c_CMD:=CHR(6) //correto
      c_TRD:=c_TRD+0
   EndIf
ElseIf a_CMD=="ADCIONA ALIQUOTA"
   If wECF_MODELO=="B"
      c_CMD:=CHR(7) //correto
      c_TRD:=c_TRD+0 
   EndIf
ElseIf a_CMD=="NUMERO CUPOM"
   If wECF_MODELO=="B"
      c_CMD:=CHR(30)  //correto
      c_TRD:=c_TRD+3
   EndIf
ElseIf a_CMD=="SUBTOTAL"
   If wECF_MODELO=="B"
      c_CMD:=CHR(29)  //correto
      c_TRD:=c_TRD+7
   EndIf
ElseIf a_CMD=="CANCELA CUPOM"
   If wECF_MODELO=="B"
      c_CMD:=CHR(14)  //correto
      c_TRD:=c_TRD+0
   EndIf
EndIf
////////////////executa
If c_ECF_TIPO=="DIRETA"
   If wECF_MODELO=="B"
      c_CMD:=c_CMD+a_TXT
   EndIf
   IBE_PREP_BUFFER()   //calcula o checksun e passa para c_CMD
   If ECF_OpenDoor()   //abre a porta = Init_Port()
      lRet:=ECF_Processo(a_CMD) //executa=outchr() e fecha=UnInt_port()
   EndIf
EndIf
Return lRet
//*
Function ECF_CHKPDV
Local aRet:=.F.
If ECF_DIRETA("PDV")
   wECF_PDV:=Right(c_ECF_DADOS,3)
   If Val(wECF_PDV)>=1
      aRet:=.T.
   EndIf
EndIf
Return aRet
//
Function ECF_OpenDoor() // abre a porta serial
Local lRet:=.F.
//fun‡Æo:
//nPorta recebe o handle e a funcao ECF_OpenDoor retorna .t. ou .f.. para validar o sistema para uso
//Init_Port( cPort, nBaudrate, nDatabits, nParity, nStopbits, nBuffersize ) --> nHandle

//Bematech:
//cport     (porta)         =   COM[1-9]
//nbaudrate (velocidade)    = 9.600 , 38.400
//ndatabist (bits grava‡ao) = 8     ,
//nParity   (paridade)      = 0     ,
//nStopBits (bits parada)   = 1     ,
//nBufferSize (tamanho a/cv)= 256   ,  8.000

If (nPorta:=Init_Port(wECF_Porta,9600,8,0,1,256))>0
                             //abre a porta inicializo a porta
                             //se maior que zero a porta ‚ iniciada
   OutBufClr(nPorta)         //limpa a porta saida  hbcomm se iniciada
   lRet:=IsWorking(nPorta)   //retorna a leitura da porta hbcomm se esta apta ao trabalho
EndIf
Return lRet  
//*
Function ECF_Processo(a_CMD) // FAZ A VARREDURA NA PORTA
Local aRet:=.F.,cBuffer:="",nBytes:=0
If c_ECF_TIPO=="DIRETA"
   nBytes :=INBUFSIZE(nPorta)    //pega o tamanho do buffer
   cBuffer:=Space(nBytes)        //cria o tamanho do buffer
   INCHR(nPorta,@cBuffer,nBytes) //compara o tamanho do buffer com a leitura atual
   If nBytes = Len(cBuffer)      //InChr(nPorta,@cBuffer,nBytes) //compara o tamanho do buffer com a leitura atual
      OUTBUFCLR(nPorta)                  //limpa a porta saida hbcomm
      If OUTCHR(nPorta,c_CMD,Len(c_CMD)) //emite o comando compara a leitura
      // tive problemas daqui pra baixo, como aguardar a leitura da porta até que cheguei nas linhas abaixo, TESTADAS E FUNCIONANDO.
         nTOut :=0                   //tempo limite time out = 0
         nTDec :=0                   //tempo decorrido = time decorrido
         nTIni :=Seconds()           //tempo iniciado  = time inicio
         nBytes:=0                   //byte a byte atualizado
         nUByte:=0                   //ultimo byte atualizado
         While nBytes < c_TRD        //fa‡a enquanto os bytes sÆo menores que o total retorno
           ShowWaitProc()            //indica o processamento
           Inkey(0.1)                //fraciona em d‚cima parte de 1 minuto = 6 segundos
           nTDec :=Seconds()-nTIni   //encrementa o tempo decorrido
           nBytes:=INBUFSIZE(nPorta) //pega o tamanho do buffer
           If nBytes>0               //se recebeu no primeiro instante o ack
              If nTOut=0             //e o time out for igual a zero
                 nTOut:=90           //90 segundos, recebe o time out
              EndIf                  //com time out de 90 segundos para garantia, visto que as matriciais sÆo mais lerdas que as termicas.
           ElseIf nBytes=0           //se nÆo conseguiu ler, houve algo errado
              nTOut:=1               //1 segundo, saia em um segundo
           EndIf
           If nBytes>nUByte          //se nBytes for maior que o ultimo bytes, atualize
              nTIni :=Seconds()      //iguala o tempo parado com tempo decorrido time out = 0 (esta em captura)
              nUByte:=nBytes         //iguala os bytes
           EndIf
           If nTDec > nTOut          //S¢ sair se o tempo ocioso for maior que nTOut
         Exit
           EndIf
         End
    // até aqui faz a leitura da porta para descobrir o tamanho dos bytes em comparação com o total a ser retornado.
         If nBytes > 0
            cBuffer    :=Space(nBytes)                     //cria o tamanho do buffer
            INCHR(nPorta,nBytes,@cBuffer)                  //le a porta serial compara a leitura do buffer
            cBuffer    :=AllTrim(cBuffer)                  //compacta o retorno
            cBuffer    :=IBE_BCD_ASC(cBuffer)              //decodifica o retorno
            c_ACK      :=Val(Left(cBuffer,2))              //pega o ACK
            c_ST1      :=Val(SubStr(Right(cBuffer,4),1,2)) //pega o ST1
            c_ST2      :=Val(SubStr(Right(cBuffer,4),3,2)) //pega o ST2
            c_ECF_DADOS:=SubStr(cBuffer,3,Len(cBuffer)-6)  //pega os DADOS
            aRet       :=ECF_Status()                      //trata o retorno ST1 e ST2
         EndIf
         OUTBUFCLR(nPorta)                                 //limpa a porta saida hbcomm
      Else
         ShowMessage(,,"Erro na verifica‡Æo dos dados.",2)
      EndIf
   Else
      ShowMessage(,,"Erro na igualdade do buffer.",2)
   EndIf
   ECF_CloseDoor(nPorta) // FECHA A PORTA  se verdadeiro
EndIf
Return aRet
//
Function ECF_CloseDoor()
UnInt_Port(nPorta) // FECHA A PORTA  se verdadeiro
nPorta:=0
Return .T.
//
Function ECF_Status
Local lRet:=.T.
ShowWait(,,"Analisando o retorno da impressora fiscal...")
wECF_MeST1:=wECF_MeST2:=""
If c_ACK=6.And.(c_ST1>0.Or.c_ST2>0) //mostra o status
   If c_ST1>=80
      wECF_MeST1:="Acabou o Papel Da Impressora Fiscal."
      c_ST1:=c_ST1-80
      lRet:=.F.
   EndIf
   If c_ST1>=40
      wECF_MeST1:="H  Pouco Papel Na Impressora Fiscal."
      c_ST1:=c_ST1-40
   EndIf
   If c_ST1>=20
      wECF_MeST1:="Erro No Rel¢gio Da Impressora Fiscal."
      c_ST1:=c_ST1-20
      lRet:=.F.
   EndIf
   If c_ST1>=10
      wECF_MeST1:="Erro Na Impressora Fiscal."
      c_ST1:=c_ST1-10
      lRet:=.F.
   EndIf
   If c_ST1>=8
      wECF_MeST1:="Primeiro Dado De CMD NÆo Foi ESC (1Bh)."
      c_ST1:=c_ST1-8
      lRet:=.F.
   EndIf
   If c_ST1>=4
      wECF_MeST1:="Comando Inexistente."
      c_ST1:=c_ST1-4
      lRet:=.F.
   EndIf
   If c_ST1>=2
      wECF_MeST1:="Cupom Aberto."
      c_ST1:=c_ST1-2
   EndIf
   If c_ST1>=1
      wECF_MeST1:="N£mero De Parƒmetros De CMD Inv lido."
      c_ST1:=c_ST1-1
      lRet:=.F.
   EndIf
   If c_ST2>=80
      wECF_MeST2:="Tipo De Parƒmetro De CMD Inv lido."
      c_ST2:=c_ST2-80
      lRet:=.F.
   EndIf
   If c_ST2>=40
      wECF_MeST2:="Mem¢ria Fiscal Lotada."
      c_ST2:=c_ST2-40
      lRet:=.F.
   EndIf
   If c_ST2>=20
      wECF_MeST2:="Erro Na Mem¢ria RAM CMOS NÆo Vol til."
      c_ST2:=c_ST2-20
      lRet:=.F.
   EndIf
   If c_ST2>=10
      wECF_MeST2:="Al¡quota NÆo Programada."
      c_ST2:=c_ST2-10
      lRet:=.F.
   EndIf
   If c_ST2>=8
      wECF_MeST2:="Capacidade De Al¡quotas Program veis Lotada."
      c_ST2:=c_ST2-8
      lRet:=.F.
   EndIf
   If c_ST2>=4
      wECF_MeST2:="Cancelamento NÆo Permitido."
      c_ST2:=c_ST2-4
      lRet:=.F.
   EndIf
   If c_ST2>=2
      wECF_MeST2:="CNPJ/IE Do Propriet rio NÆo Programados."
      c_ST2:=c_ST2-2
      lRet:=.F.
   EndIf
   If c_ST2>=1
      wECF_MeST2:="Comando NÆo Executado."
      c_ST2:=c_ST2-1
      lRet:=.F.
   EndIf
   If !Empty(wECF_MeST1).Or.!Empty(wECF_MeST2)
      ShowMessage(,,{wECF_MeST1+"",""+wECF_MeST2},0)
//      lRet:=If(Empty(wECF_MeST2),lRet,.F.)
   EndIf
EndIf
CloseWindow()
Return lRet

//////////////fim do ecf

[/color]

Um abraço a todos usuários do fórum.
:xau
Harbour 3.2 + GtWVW + QT + SQLite3 + DBF + SQL (Firebird)
Responder