Página 1 de 1

Acesso via Socket TCP/IP

Enviado: 14 Nov 2006 09:32
por rmg
Instalei hoje o programa ACBrMonitor em minha máquina no Windows. Tenho um sistema no xHarbour/Linux usado via ssh pelo Putty no Windows.

Como posso fazer para enviar comandos para o programa ACBrMonitor via socket do meu programa no Linux, na porta 3434 por exemplo?

Aguardo a ajuda dos amigos...

Enviado: 14 Nov 2006 11:25
por vagucs
Renato, quando estive em tatui com o Daniel que é o mentor criador deste excelente projeto, eu fiz para ele uma classe em xHarbour para acesso ao ACBR, na epoca decidimos nao disponibilizar junto com a ACBR pois queriamos fazer algo mais especifico, fiquei até de contribuir para o projeto mas não o fiz, nao sei ainda se o Daneil está disponibilizando os fontes junto com a ACBR, a ultima atualização que fiz do CVS eles nao estavam la, quando estiver em casa posso te passar isto, mas isto so vai acontecer mesmo no final do ano, que to emperrado aqui.

A instabilidade de operações com Sockets é algo real, eu achei que nao existia, falta no protocolo da ACBR uma marcação para evitar esta perda de dados, apesar de que o Daniel nunca teve problemas com isto, a ACBR é muito boa e funciona muito bem e é uma forma genérica para se trabalhar com qualquer impressora fiscal.

Enviado: 16 Nov 2006 21:39
por dopi
Segue abaixo o PRG que estou usando atualmente... Ele se comunica com o ACBrMonitor por TXT (Clipper) ou TCP (apenas xHarbour)

A rotina abaixo não está "pronta para uso" em qualquer sistema... É necessário adapta-la, removendo chamadas de rotinas específicas minhas... Mas acredito que estudando os fontes não deva ser difícil adapta-lo as suas necessidades.

Estude com atenção as funções: IBR_INIT, IBR_END e IBR_COMANDO

Código: Selecionar todos

* PRG......................: IMPACBR
* CLASSE...................: Impressora Fiscal com ACBrMonitor
* DESC.....................: Abre porta, envia comandos, fecha porta
* PREFIXO..................: IBR
* EXPORTADORA..............: IBR_*
* CONSTRUTORA..............: IBR_INIT()
* DESTRUTORA...............: IBR_END()
* USA......................:
* NOTAS....................: Deve ser compilada com /n uma vez que utiliza
*                            estatica externa. Nao ha construtora.
*                            Trapaceamos e inicializamos com uma estatica
*                            externa!

#include "fileio.ch"
#include "commands.ch"

#define  ETX chr(3)
#define  CR  chr(13)
#define  LF  chr(10)

#define ENT_TXT  'ENT.TXT'
#define SAI_TXT  'SAI.TXT'
#define TMP_TXT  'ENT.TMP'

Static sENDER   := ''  ,;
       SEM_ERRO := .F. ,;
       sSECHORA := 0   ,;
       sRETHORA := ''  ,;
       sSECCOO  := 0   ,;
       sNUMCUPOM:= ''  ,;
       sSECEST  := 0   ,;
       sESTADO  := ''

#ifdef __XHARBOUR__
Static sSOCKET
#endif

************************************************************************
Function IBR_INIT(ENDERECO)   // Abre a comunicação com o ACBrmonitor
************************************************************************
Local P, RET := .T., TFIM, IP, PORTA, RESP

if ! empty(sENDER)  // J  est  aberto...
   return .t.
endif

SEM_ERRO := .F.
sENDER   := alltrim(ENDERECO)
IP       := ''
PORTA    := 0

#ifdef __XHARBOUR__
if ! (PATH_DEL $ sENDER)   /// Abrir comunicacao TCP/IP
   P := at(':',sENDER)
   if P = 0
      P := len(sENDER)+1
   endif

   IP    := substr(sENDER,1,P-1)
   if empty(IP)
      RET := .F.
   else
      PORTA := val(substr(sENDER,P+1))
      if PORTA = 0
         PORTA := 3434
      endif

      inetinit()
      RET := .F.

      TFIM := Seconds() + 5             /// Tenta conectar durante 5 segundos ///
      do while Seconds() < TFIM .and. ! RET
         sSOCKET := inetconnect(IP,PORTA)
         RET     := (ineterrorcode(sSOCKET) = 0)

         millisec(200)
      enddo
   endif

   if RET
      InetSetTimeout( sSOCKET, 3000 )   // Timeout de Recepção 3 seg //
      RESP := InetRecvEndBlock( sSOCKET, ETX )
      RET  := ('ACBrMonitor' $ RESP )   // Recebeu as boas vindas ?
   endif
endif
#endif

if PATH_DEL $ sENDER   /// Abrir comunicacao TXT
   if right(sENDER,1) <> PATH_DEL
      sENDER := sENDER + PATH_DEL
   endif
endif

if ! RET
   sENDER := ''
endif

return RET

************************************************************************
Function IBR_END()   // Fecha a porta da Impressora
* Encerra a cominicacao com a impressora, nao precisa de parametros
************************************************************************

#ifdef __XHARBOUR__
if ! PATH_DEL $ sENDER   /// Fechar comunicacao TCP/IP
   if ! empty(sENDER)
      inetsendall( sSocket, 'ACBR.bye' )
   endif

   if sSOCKET <> NIL
      inetclose(sSOCKET)
      inetdestroy(sSOCKET)
      inetcleanup()
      millisec(20)
      sSOCKET := NIL
   endif
endif
#endif

sENDER := ''

return .t.

************************************************************************
Function IBR_ABERTA()   // Retorna .t. se a COM ja est  aberta
************************************************************************

return ! empty(sENDER)

************************************************************************
Function IBR_OK(RESP)   // Retorna .T. se a String inicia com OK:
************************************************************************

return (substr(RESP,1,3) == 'OK:')

************************************************************************
Function IBR_ZERA()   // Reseta Impressora em ERRO, Retorna .t. se OK
************************************************************************

return IBR_OK( IBR_COMANDO( 'CorrigeEstadoErro', , 40 ))

************************************************************************
Function IBR_TEF_INIT()   // Carrega na mem¢ria vetores com Planos de
*                            Pagamento e CNF
************************************************************************

IBR_FIM_REL()
return IBR_OK( IBR_COMANDO( 'PreparaTEF', , 8 ) )

************************************************************************
Function IBR_LEITURAX()   // Imprime relatorio de Leitura X, retorna .t. se ok
************************************************************************

return IBR_OK( IBR_COMANDO( 'LeituraX', , 45 ) )

************************************************************************
Function IBR_REDUCAOZ()   // Imprime relatorio de Reducao Z, retorna .t. se ok
************************************************************************

return IBR_OK( IBR_COMANDO( 'ReducaoZ', {dtoc(date())+' '+time()}, 40 ))


************************************************************************
Function IBR_ESTADO()
* Retorna .t. se Iniciou o Fechamento do Cupom e estiver esperando
* Formas de Pagamento
************************************************************************
Local RET

if sSECEST <> seconds()
   RET := IBR_COMANDO( 'Estado' )
   if left(RET,3) == 'OK:'
      sESTADO := upper(alltrim(substr(RET,5)))
      sSECEST := seconds()
   else
      sESTADO := ''
   endif
endif

return sESTADO

************************************************************************
Function IBR_DATA()   // Le a Data gravada na Impressora
* Retorna a data da impressora no tipo DATE
************************************************************************
Local RET

if sSECHORA <> seconds()
   RET := IBR_COMANDO( 'DataHora' )
   if left(RET,3) == 'OK:'
      sRETHORA := RET
      sSECHORA := seconds()
   else
      sRETHORA := ''
   endif
endif

return ctod(substr(sRETHORA,5,8))

************************************************************************
Function IBR_HORA()   // Le a Hora gravada na Impressora
* Retorna uma string com a hora da impressora
************************************************************************
Local RET

if sSECHORA <> seconds()
   RET := IBR_COMANDO( 'DataHora' )
   if left(RET,3) == 'OK:'
      sRETHORA := RET
      sSECHORA := seconds()
   else
      sRETHORA := ''
   endif
endif

return substr(sRETHORA,14,8)

************************************************************************
Function IBR_VERAO()   // Entra ou Sai do Hor rio de Verao, retorna .T. se ok
************************************************************************

return IBR_OK( IBR_COMANDO( 'MudaHorarioVerao', , 8 ) )

************************************************************************
Function IBR_NUM_CUPOM()   // Le o Numero do ultimo Cupom,
* Retorna string tamanho 6 com o numero do ultimo cupom
************************************************************************
Local RET

if sSECCOO <> seconds()
   RET := IBR_COMANDO( 'NumCupom' )
   if left(RET,3) == 'OK:'
      sNUMCUPOM := StrZero(val(substr(RET,5)),6)
      sSECCOO   := seconds()
   else
      sNUMCUPOM := '000000'
   endif
endif

return sNUMCUPOM

************************************************************************
Function IBR_SUBTOTAL()   // Retorna o Subtotal do cupom aberto
************************************************************************
Local WSTR

WSTR := substr(IBR_COMANDO( 'SubTotal' ),5)

return val(StrTran(WSTR,',','.'))

************************************************************************
Function IBR_TOTALPAG()   // Retorna o Total de Pagamentos efetuados
************************************************************************
Local WSTR

WSTR := substr(IBR_COMANDO( 'TotalPago' ),5)

return val(StrTran(WSTR,',','.'))

************************************************************************
Function IBR_NUM_CAIXA()   // Le o Numero do caixa
* Retorna string tamanho 4 com o numero do caixa da impressora,
* geralmente '0001' a nao ser que no estabelecimento existam 2 impressoras
************************************************************************
Static sNumECF := ''

if val(sNumECF) = 0
   sNumECF := StrZero(val(substr(IBR_COMANDO( 'NumECF' ),5)),4)
endif

return sNumECF

************************************************************************
Function IBR_NUM_SERIE()   // Retorna o Numero de S‚rie da Impressora
************************************************************************
Static sNumSerie := ''

if empty(sNumSerie)
   sNumSerie := Alltrim(substr(IBR_COMANDO( 'NumSerie' ),5))
endif

return sNumSerie

************************************************************************
Function IBR_VERSAO()   // Le o Numero de versao da impressora 4 dig.
************************************************************************
Static sVersao := ''

if empty(sVersao)
   sVersao := Alltrim(substr(IBR_COMANDO( 'NumVersao' ),5))
endif

return sVersao

************************************************************************
Function IBR_POUCO_PAPEL()  // Retorna .t. se for pouco papel
************************************************************************

return (upper(substr(IBR_COMANDO( 'PoucoPapel' ),5,5)) = 'TRUE')

************************************************************************
Function IBR_CUPOM_ABERTO()  // Retorna .t. se cupom estiver aberto
************************************************************************

return (IBR_ESTADO() = 'ESTVENDA')

************************************************************************
Function IBR_PODE_ABRIR()  // Retorna .t. se pode abrir novo cupom
************************************************************************

return IBR_OK( IBR_COMANDO( 'TestaPodeAbrirCupom' ) )

************************************************************************
Function IBR_CHEQUE(WBANCO,WVALOR,WFAVORECIDO,WCIDADE,WDATA,WOBS)
* Imprime cheque, necessita de BANCOS.TXT no mesmo diretorio do DRIVER,
* retorna .T. se ok
************************************************************************

return IBR_OK( IBR_COMANDO( 'ImprimeCheque', {WBANCO, WVALOR, WFAVORECIDO,;
                                              WCIDADE, WDATA, WOBS}, 30 ))

************************************************************************
Function IBR_COM_CHEQUE()  // Retorna .t. se sensor de COM PAPEL ok
************************************************************************

return (upper(substr(IBR_COMANDO( 'ChequePronto' ),5,5)) = 'TRUE')

************************************************************************
Function IBR_CAN_CHEQUE()  // Cancela Impressao de cheque, retorna .t. se conseguiu
************************************************************************

return IBR_OK( IBR_COMANDO( 'CancelaImpressaoCheque' ) )

************************************************************************
Function IBR_ABRE_CUPOM(WCGC)   // Abre Cupom Fiscal, Retorna .t. se ok
* WCGC, SE RECEBIDO imprime o CGC do cliente no cabecalho
************************************************************************
sSECCOO := 0
return IBR_OK( IBR_COMANDO( 'AbreCupom',{WCGC}, 8 ) )

************************************************************************
Function IBR_ACHA_PG(WPAGAMENTO,WVINC)  // Retorna codigo do Totalizador (String 2)
* equivalente a Forma de Pagamento passada se nao encontrar tenta cadastrar
* se conseguir retorna o novo numero, se nao conseguir encontrar nem
* cadastrar retorna "  "
* WPAGAMENTO -> String de 16, com Pagamento a localizar/Cadastra.
* WVINC -> Passado por referencia, Informa.T. se a Forma de Pagamento pode
*          imprimir Cupom Fiscal Vinculado
************************************************************************
Local RET_IMP, RET:=''

SEM_ERRO := .T.
RET_IMP := IBR_COMANDO( 'AchaFPGDescricao',{alltrim(WPAGAMENTO)}, 6 )
SEM_ERRO := .F.
if IBR_OK( RET_IMP )
   RET_IMP := substr(RET_IMP,5)

   if ! empty(RET_IMP)
      RET := alltrim(substr(RET_IMP,1,4))
      WVINC := (substr(RET_IMP,5,1)<>' ')
   endif
endif

return RET

/*
Static VET_PLA:={}
Local RET_IMP,P,S,RET

DEFAULT WPAGAMENTO to ''

if empty(VET_PLA)
   RET_IMP := IBR_COMANDO( 'CarregaFormasPagamento', ,  5 )
   if IBR_OK( RET_IMP )
      RET_IMP := substr(RET_IMP,5)

      do while ! empty(RET_IMP)
         P := at('|',RET_IMP)
         if P = 0
            P := len(RET_IMP)+1
         endif

         S := substr(RET_IMP,1,P-1)

         aadd(VET_PLA, {substr(S,1,4), (substr(S,5,1)<>' '), Alltrim(substr(S,6))} )
         RET_IMP := substr(RET_IMP,P+1)
      enddo
   endif
endif

WPAGAMENTO := Alltrim(upper(WPAGAMENTO))
POS        := ascan(VET_PLA,{|x|upper(x[3])==WPAGAMENTO})
WVINC      := .F.
RET        := ''
if POS > 0
   RET   := VET_PLA[POS,1]
   WVINC := VET_PLA[POS,2]
endif

return RET
*/

************************************************************************
Function IBR_FECHA_CUPOM(WVAL_VISTA,WVAL_DESC,WMSG,WDESC_PLA,WA_D,WCOLUNAS,WAVISTA)
* FECHA Cupom Fiscal, retorna .t. se ok
* WVAL_VISTA -> Numerico, Valor A VISTA ou ENTRADA pago pelo cliente
*               (usado para calcular o troco)
* WVAL_DESC -> Numerico, Desconto/Acrescimo em VALOR, concedido para o cliente
* WMSG -> String, Mensagem promocional, linhas separadas por '|'
* WA_D -> String, 'a' - acrescimo, 'd' - desconto (Assume 'd' se omitida)
* WDESC_PLA -> Descricao do Plano de Pagamento
* WCOLUNAS -> Numero de caracteres por linha permitidas no cupom
* WAVISTA -> Se for .t. Considera sempre a vista
************************************************************************
Local WMSG2,VET,A,WSUB_TOTAL, WCODAV, WCODAP, ESPERA, RET:=.T.,;
      WVAL_PRAZO  // Calculado se WVAL_VISTA for menor que SUBTOTAL

sSECCOO := 0
if ! IBR_INI_FECHA( WVAL_DESC * iif(lower(WA_D)='a',1,-1) )
   return .f.
endif

WSUB_TOTAL := IBR_SUBTOTAL()

if ! WAVISTA
   if WSUB_TOTAL <= 0
      ALERTA('Subtotal retornado pela impressora ‚: '+transform(WSUB_TOTAL,'@E 999.99')+;
             '|Cupom ser  considerado A VISTA.',,,COR_ERRO)
      WAVISTA := .T.
   else
      WCODAP := IBR_ACHA_PG('A PRAZO')

      if empty(WCODAP)
         ALERTA('Forma de pagamento A PRAZO n†o encontrada.|'+;
                'Cupom ser  considerado A VISTA.',,,COR_ERRO)
         WAVISTA := .T.
      endif
   endif
endif

if WAVISTA
   WVAL_VISTA := max(WSUB_TOTAL,WVAL_VISTA)
   WVAL_PRAZO := 0
else
   WVAL_PRAZO := max(ROUNDING(WSUB_TOTAL - WVAL_VISTA,2),0)
endif

//// Efetua formas de pagamento A VISTA e A PRAZO ////
if ! empty(WVAL_VISTA)
   if ! (lower(alltrim(substr(IBR_COMANDO('modelo'),4))) == 'ecfbematech')
      WCODAV := IBR_ACHA_PG('A VISTA')
   endif

   WCODAV := iif( empty(WCODAV), '01', WCODAV)

   RET := IBR_PAGTO( WVAL_VISTA , WCODAV )
endif

if RET .and. ! empty(WVAL_PRAZO)
   RET := IBR_PAGTO( WVAL_PRAZO , WCODAP )
endif

if RET
   RET := IBR_FIM_FECHA( WMSG )
endif

return RET

************************************************************************
Function IBR_FECHANDO()
* Retorna .t. se Iniciou o Fechamento do Cupom e estiver esperando
* Formas de Pagamento
************************************************************************

return (IBR_ESTADO() = 'ESTPAGAMENTO')

************************************************************************
Function IBR_INI_FECHA( WDESC_ACRES )
* Inicia FECHAMENTO de Cupom Fiscal com Formas de Pagto, retorna .t. se OK
* WDESC_ACRES -> Numerico, Desconto/Acrescimo em VALOR, concedido para o
*                cliente. Se positivo ACRESCIMO senao DESCONTO
************************************************************************

return IBR_OK( IBR_COMANDO( 'SubTotalizaCupom',{WDESC_ACRES}, 5 ))

************************************************************************
Function IBR_PAGTO( WVALOR, WCODFPG, WOBS, WVINC )
* Efetua Pagamento em Cupom. Deve ser executada apos IBR_INI_FECHA
* Retorna .t. se OK
* WVALOR -> Valor Numerico pago pela Forma de Pagamento
* WCODFPG -> Codigo da Forma de Pagamento, pode ser achado com IBR_ACHA_PG
* WOBS -> Texto de 80 caracteres para OBS
* WVINC -> Boleano, se .t. ter  Cupom NAO Fiscal vinculado a esta FPG
*          (nao ‚ necess rio na Bematech)
************************************************************************

return IBR_OK( IBR_COMANDO( 'EfetuaPagamento',{WCODFPG, WVALOR, WOBS, WVINC}) )

************************************************************************
Function IBR_FIM_FECHA( WMSG, WCOLUNAS )
* FECHA Cupom Fiscal, retorna .t. se OK
* WMSG -> String, Mensagem promocional, linhas separadas por '|'
*         checagem de colunas ‚ feita por IMF_FIM_FECHA
* WCOLUNAS -> ajustada por PAI IMF_FIM_FECHA
************************************************************************

sSECCOO := 0
return IBR_OK( IBR_COMANDO( 'FechaCupom',{WMSG}, 20 ) )

************************************************************************
Function IBR_ITEM(WCODIGO,WDESCRICAO,WALIQ,WQTD,WVALOR_UNIT,WDESCONTO,WUN)
* Efetua venda de itens no cupom Fiscal, retorna .t. se OK
* WCODIGO -> String, Codigo do produto 13 caracteres
* WDESCRICAO -> String, Descricao do produto 29 caracteres
* WALIQ -> % da aliquita a ser impressa, a rotina acha o totalizador
   * Se a aliquota for numerica, procura o totalizador, senao,
   * usa o propria aliquota que foi passada ('01','02','FF','NN',...)
   * FF - Totalizador de Substituicao Tributaria,
   * II - Totalizador parcial de Isen‡ao
   * NN - Totalizador parcial de NAO incidencia
* WQTD -> Numerico, Quantidade a ser impressa, a rotina ajusta a mascara
* WVALOR_UNIT -> Numerico, Valor Unitario do Produto, a rotina ajusta a mascara
* WDESCONTO -> Numerico, Desconto em % para aplicar, a rotina ajusta a mascara
* WUN - Descricao da unidade (se nulo assume 'UN')
************************************************************************

return IBR_OK( IBR_COMANDO( 'VendeItem',{WCODIGO, WDESCRICAO, WALIQ, WQTD,;
                                         WVALOR_UNIT, WDESCONTO, WUN} ) )

************************************************************************
Function IBR_ACHA_ALIQ(WALIQ)  // Retorna codigo do Totalizador (String 2)
* equivalente a WALIQ passada, se nao encontrar volta "  "
* WALIQ -> Numerico, % do ICMS a localizar o Totalizador.
************************************************************************
Static VET_ALIQ
Local POS:=0

if VET_ALIQ = NIL
   VET_ALIQ := IBR_ALIQ()
endif

POS := ascan(VET_ALIQ,{|x|x[1] = WALIQ})

return iif(empty(POS),"  ",VET_ALIQ[POS,2])

************************************************************************
Function IBR_ALIQ()  // Retorna vetor bi-dimensional com os codigos
* das aliquotas no formato {ALIQ(N 5,2),COD_ALIQ(C 2)}
* Fun‡ao de uso interno, pela funcao (IBR_ACHA_ALIQ())
************************************************************************
Local RET_IMP,VET_RET:={},P,S

RET_IMP := IBR_COMANDO( 'CarregaAliquotas', , 5 )
if IBR_OK( RET_IMP)
   RET_IMP := substr(RET_IMP,5)

   do while ! empty(RET_IMP)
      P := at('|',RET_IMP)
      if P = 0
         P := len(RET_IMP)+1
      endif

      S := substr(RET_IMP,1,P-1)

      aadd(VET_RET, {val(strtran(substr(S,6,6),',','.')), substr(S,1,4)} )
      RET_IMP := substr(RET_IMP,P+1)
   enddo
endif

return VET_RET

***********************************************************************
Function IBR_CAN_CUPOM()  // Cancela Cupom fiscal, retorna .t. se ok
***********************************************************************

return IBR_OK( IBR_COMANDO( 'CancelaCupom', , 14 ) )

************************************************************************
Function IBR_CAN_ITEM(WITEM)  // Cancela Item do Cupom fiscal, retona .t. se ok
* WITEM -> Numerico com Codigo sequencial do Item a cancaler
*  Ex.: 1 cancela o primeiro item vendido.
************************************************************************

return IBR_OK( IBR_COMANDO( 'CancelaItemVendido',{WITEM}) )

************************************************************************
Function IBR_RELATORIO(WTXT,WVIAS,WCOLUNAS) // Imprime relatorio Gerencial
* Retorna .T. se imprimiu com sucesso
* WTXT  -> texto a Imprimir no relatorio, quebra de linhas = '|'
* WVIAS -> Numero de vias a imprimir 1 ou 2, padrao 1
* WCOLUNAS -> Numero m ximo de colunas da impressora, ajustada por IMF_RELATORIO
************************************************************************
Local VET,A,RET,WIMP

DEFAULT WVIAS to 1

VET  := SEPARA_STR(WTXT,'|')  // Separa as linhas de WTXT
WIMP := 0
RET  := .T.

IBR_FIM_REL()   // Fecha se ficou algum aberto

//// Imprime relatorio gerencial ////
MSG_SAVE('Aguarde Imprimindo Relat¢rio...')
RET := IBR_OK( IBR_COMANDO( 'AbreRelatorioGerencial', , 45 ) )

do while RET
//   A := 1
//   do while RET .and. A <= len(VET)
//      RET := IBR_OK( IBR_COMANDO( 'LinhaRelatorioGerencial',{VET[A]} ) )
//      A++
//   enddo

   RET := IBR_OK( IBR_COMANDO( 'LinhaRelatorioGerencial',{WTXT}, Int(len(VET)/1.5)+4 ) )

   WIMP++

   if ! RET .or. WIMP >= WVIAS
      exit
   endif

   IBR_COMANDO( 'LinhaRelatorioGerencial',{' | | | | | | '}, 5 )
   clear typeahead
   MSG('  **  DESTAQUE A '+trim(str(WIMP,2))+'¦ VIA **              ENTER - Imprime pr¢xima via',8)
enddo

if RET
   RET := IBR_FIM_REL()
endif

clear typeahead
MSG_REST()

return RET

************************************************************************
Function IBR_VINCULADO(WCOO,WCODFPG,WVALOR,WTXT,WVIAS,WCOLUNAS)
* Imprime Comprovante NAO fiscal VINCULADO, Retorna .T. se imprimiu ok
* WCOO -> Numero do Cupom para Vincular
* WCODFPG -> Forma de Pagamento executada no Cupom a vincular
* WVALOR -> Valor pago atraves da Forma de Pagamento
* WTXT  -> texto a Imprimir no relatorio, quebra de linhas = '|'
* WVIAS -> Numero de vias a imprimir 1 ou 2, padrao 1
* WCOLUNAS -> Numero m ximo de colunas da impressora, ajustada por IMF_RELATORIO
************************************************************************
Local VET,A,RET,WIMP

DEFAULT WVIAS to 1

WCOO := strzero(val(WCOO),6)

//// Abrindo Comprovante NAO fiscal Vinculado ////
MSG_SAVE('Aguarde Imprimindo Cupom Vinculado...')
RET := IBR_OK( IBR_COMANDO( 'AbreCupomVinculado',{WCOO, WCODFPG, WVALOR}, 10 ) )

VET  := SEPARA_STR(WTXT,'|')  // Separa as linhas de WTXT
WIMP := 0

//// Imprime relatorio gerencial ////
do while RET
   A := 1
//   do while RET .and. A <= len(VET)
//      RET := IBR_OK( IBR_COMANDO( 'LinhaCupomVinculado',{VET[A]} ) )
//      A++
//   enddo

   RET := IBR_OK( IBR_COMANDO( 'LinhaCupomVinculado',{WTXT}, Int(len(VET)/1.5)+4 ) )

   WIMP++

   if ! RET .or. WIMP >= WVIAS
      exit
   endif

   IBR_COMANDO( 'LinhaCupomVinculado',{' | | | | | | '}, 5 )
   clear typeahead
   MSG('  **  DESTAQUE A '+trim(str(WIMP,2))+'¦ VIA **              ENTER - Imprime pr¢xima via',8)
enddo

if ! IBR_FIM_REL()
   RET := .F.
endif

clear typeahead
MSG_REST()

return RET

************************************************************************
Function IBR_FIM_REL() // Encerra relatorio Gerencial e ou C.V.
************************************************************************
local RET

SEM_ERRO := .T.
RET := IBR_OK( IBR_COMANDO( 'FechaRelatorio', , 20 ) )
SEM_ERRO := .F.

return RET

***********************************************************************
Function IBR_ABRE_GAVETA()  // Abre Gaveta da Impressora, retorna .t. se abriu
***********************************************************************

IBR_COMANDO( 'AbreGaveta', , 6 )

return IBR_GAVETA_ABERTA()


***********************************************************************
Function IBR_GAVETA_ABERTA()  // Retorna .t. se Gaveta est  aberta
***********************************************************************

return (upper(substr(IBR_COMANDO( 'GavetaAberta' ),5,5)) = 'TRUE')


************************************************************************
Function IBR_COMANDO(CMD,VET_PARAM,ESPERA,TENTA)
* Funcao de uso interno para enviar os comandos para a impressora e
* registrar os erros retornados pela mesma. Exibe os erros se existirem
************************************************************************
Local RET_IMP, REQ, RESP, TEMPOR, TINI, TFIM, BLOCO, BYTES, I, TIPO_PARAM

if empty(sENDER)
   if ! SEM_ERRO
      ALERTA('ACBrMonitor n†o foi inicializado.',,,COR_ERRO)
   endif

   return ''
endif

DEFAULT VET_PARAM   to {} ,;
        ESPERA      to 0  ,;
        TENTA       to .t.

///// Codificando CMD de acordo com o protocolo /////
RET_IMP  := ''

if ! ('.' $ left(CMD,5))   // Informou o Objeto no Inicio ?
   CMD := 'ECF.'+CMD       // Se nao informou assume ECF.
endif

if len(VET_PARAM) > 0
   CMD := CMD + '(' ;

   For I := 1 to len(VET_PARAM)
     TIPO_PARAM := valtype(VET_PARAM[I])

     if TIPO_PARAM = 'C'
        // Converte aspas para simples para aspas duplas, para o ACBrMonitor
        CMD := CMD + '"'+ StrTran( RTrim(VET_PARAM[I]), '"', '""' ) + '"'

     elseif TIPO_PARAM = 'N'
        CMD := CMD + strtran(alltrim(Str(VET_PARAM[I])),',','.')

     elseif TIPO_PARAM = 'D'
        CMD := CMD + dtoc( VET_PARAM[I] )

     elseif TIPO_PARAM = 'L'
        CMD := CMD + iif( VET_PARAM[I],'TRUE','FALSE')

     endif

     CMD := CMD + ', '
   next

   CMD := substr(CMD,1,len(CMD)-2) + ')'
endif

CMD := CMD + CR+LF

if ! SEM_ERRO
   ESPERA := max(ESPERA,5)
else
   TENTA := .F.
endif

if PATH_DEL $ sENDER               /// E' TXT ? ///
   REQ    := sENDER + ENT_TXT
   RESP   := sENDER + SAI_TXT
   TEMPOR := sENDER + TMP_TXT

   //////// Transmitindo o comando /////////
   TFIM := seconds() + 3    // Tenta apagar a Resposta anterior em ate 3 segundos
   do while file( RESP )
      if ferase( RESP ) = -1
         if (seconds() > TFIM)
            RET_IMP := 'ERRO: Nao foi possivel apagar o arquivo: ('+RESP+') '+;
                       ErrorOsMessage(ferror())
         else
            millisec(20)
         endif
      endif
   enddo

   do while empty(RET_IMP)
      TFIM := seconds() + 3    // Tenta apagar a Requisicao anterior em ate 3 segundos
      do while file( REQ )
         if ferase( REQ ) = -1
            if (seconds() > TFIM)
               RET_IMP := 'ERRO: Nao foi possivel apagar o arquivo: ('+REQ+') '+;
                          ErrorOsMessage(ferror())
            else
               millisec(20)
            endif
         endif
      enddo

      // Criando arquivo TEMPORARIO com a requisicao //
      if empty(RET_IMP)
         if ! Grava_ARQ(TEMPOR, CMD)

            RET_IMP := 'ERRO: Nao foi possivel criar o arquivo: ('+TEMPOR+') '+;
                       ErrorOsMessage(ferror())
         endif
      endif

      // Renomeando arquivo TEMPORARIO para REQUISICAO //
      if empty(RET_IMP)
         if frename(TEMPOR, REQ) = -1
            RET_IMP := 'ERRO: Nao foi possivel renomear ('+TEMPOR+') para ('+REQ+') '+;
                       ErrorOsMessage(ferror())
         endif
      endif

      // Espera ACBrMonitor apagar o arquivo de Requisicao em ate 7 segundos
      // Isso significa que ele LEU o arquivo de Requisicao
      TFIM := seconds() + 7
      do while empty(RET_IMP) .and. (seconds() <= TFIM) .and. file(REQ)
         millisec(20)
      enddo

      if file(REQ)
         if ! TENTA
            RET_IMP := 'ERRO: ACBrMonitor nao esta ativo'
         else
            if ALERTA('O ACBrMonitor n†o est  ativo|'+;
                      'Deseja tentar novamente ?',{'SIM','NAO'},,COR_ERRO) # 1
               RET_IMP := 'ERRO: ACBrMonitor nao esta ativo'
            else
               if ! file(REQ)  // ACBrMonitor "acordou" enquanto perguntava
                  exit
               endif
            endif
         endif
      else
         exit
      endif
   enddo

   //////// Lendo a resposta ////////
   TINI   := Seconds()
   TELA   := savescreen(23,1,23,78)
   do while empty(RET_IMP)
      if file(RESP)
         RET_IMP := alltrim(memoread( RESP ))
      endif

      if empty(RET_IMP)
         if Seconds() > (TINI + 5)
             @ 23, 2 say pad('Aguardando resposta do ACBrMonitor:  '+; // '('+ProcName(2)+') '+;
                         Trim(str(TINI + ESPERA - seconds(),2)),77) color COR_MENU
         endif

         if Seconds() > (TINI + ESPERA)
            restscreen(23,1,23,78,TELA)

            if ! TENTA
               RET_IMP := 'ERRO: Sem resposta do ACBrMonitor em '+alltrim(str(ESPERA))+;
                          ' segundos (TimeOut)'
            else
               if ALERTA('O ACBrMonitor n†o est  respondendo|'+;
                         'Deseja tentar novamente ?',{'SIM','NAO'},,COR_ERRO) # 1
                  RET_IMP := 'ERRO: Sem resposta do ACBrMonitor em '+alltrim(str(ESPERA))+;
                             ' segundos (TimeOut)'
               else
                  TINI := Seconds()
               endif
            endif
         endif

         millisec(20)
      endif
   enddo
   restscreen(23,1,23,78,TELA)

//   ferase( strtran(RESP,'.TXT','.OLD') )
//   frename( RESP, strtran(RESP,'.TXT','.OLD') )
   ferase( RESP )
#IFDEF __XHARBOUR__

else                                       //// TCP / IP (apenas xHarbour ) ///
   //////// Transmitindo o comando /////////
   InetSetTimeout( sSOCKET, 3000 )   // Timeout de Envio 3 seg //
   if inetsendall( sSocket, CMD ) <= 0
      RET_IMP := 'ERRO: Nao foi possivel transmitir dados para o ACBrMonitor|'+;
                 '('+AllTrim(Str(InetErrorCode( sSOCKET )))+') '+;
                 InetErrorDesc( sSOCKET ) + ETX
   endif

   //////// Lendo a resposta ////////
   InetSetTimeout( sSOCKET, 500 )
   TINI   := Seconds()
   TELA   := savescreen(23,1,23,78)
   do while (right(RET_IMP,1) <> ETX)
      BLOCO := space(64)

      BYTES   := inetrecv(sSOCKET, @BLOCO, 64)
      RET_IMP += left(BLOCO,BYTES)

      if Seconds() > (TINI + 5)
          @ 23, 2 say pad('Aguardando resposta do ACBrMonitor:  '+; // '('+ProcName(2)+') '+;
                      Trim(str(TINI + ESPERA - seconds(),2)),77) color COR_MENU
      endif

      if Seconds() > (TINI + ESPERA)
         restscreen(23,1,23,78,TELA)

         if ! TENTA
            RET_IMP := 'ERRO: Sem resposta do ACBrMonitor em '+alltrim(str(ESPERA))+;
                       ' segundos (TimeOut)' + ETX
         else
            if ALERTA('O ACBrMonitor n†o est  respondendo|'+;
                      'Deseja tentar novamente ?',{'SIM','NAO'},,COR_ERRO) # 1
               RET_IMP := 'ERRO: Sem resposta do ACBrMonitor em '+alltrim(str(ESPERA))+;
                          ' segundos (TimeOut)' + ETX
            else
               TINI := Seconds()
            endif
         endif
      endif
   enddo
   restscreen(23,1,23,78,TELA)
#ENDIF
endif

//if substr(RET_IMP,1,3) <> 'OK:' .or. substr(RET_IMP,1,5) == 'ERRO:'
//   ALERTA('RETORNO INVALIDO INIFIM|'+RET_IMP+'|'+ alltrim(memoread( RESP )) )
//endif

do while right(RET_IMP,1) $ CR+LF+ETX   // Remove sinalizadores do final
   RET_IMP := left(RET_IMP,len(RET_IMP)-1)
enddo

if ! SEM_ERRO
   MSG_ERRO := ''
   if substr(RET_IMP,1,5) == 'ERRO:'
      MSG_ERRO := 'Erro ACBrMonitor|'+;  //  'Rotina ('+ProcName(2)+')|'+;
                  strtran(strtran( MUDA_ACENTOS(substr(RET_IMP,7)),CR,''),LF,'|')
   endif

   if ! empty(MSG_ERRO)
      ALERTA(MSG_ERRO,,,COR_ERRO)
      RET_IMP := ''
   endif
endif

//if substr(RET_IMP,1,3) <> 'OK:' .or. substr(RET_IMP,1,5) == 'ERRO:'
//   ALERTA('RETORNO INVALIDO FIM|'+RET_IMP+'|'+ alltrim(memoread( RESP )) )
//endif

return RET_IMP




Static Function Grava_ARQ( WARQ, WTXT )
Local HANDLE, RET := .T.

HANDLE := fcreate(WARQ, FC_NORMAL )
if HANDLE > 0
   fwrite(HANDLE, WTXT + chr(13) + chr(10) )
   RET := (ferror() = 0)

   fclose(HANDLE)
endif

RETURN RET

Enviado: 16 Nov 2006 21:46
por dopi
Em commands.ch temos:

Código: Selecionar todos

#IFDEF __PLATFORM__Linux
 #DEFINE PATH_DEL '/'
 #DEFINE DIR_DEL ''
 #DEFINE K_GO_TOP    409
 #DEFINE K_GO_BOTTOM 417
#ELSE
 #DEFINE PATH_DEL '\'
 #DEFINE DIR_DEL ':'
 #DEFINE K_GO_TOP    chr(31)
 #DEFINE K_GO_BOTTOM chr(30)
#ENDIF

**************** COMANDOS DEFINIDOS PELO USUARIO ****************

* DEFAULT -> Caso a variavel seja nula substitui pelo valor passado.
#command DEFAULT <p> TO <val> [,<pn> TO <valn>]                     ;
         =>                                                         ;
         <p> = iif(<p> = NIL,<val>,<p>)                             ;
         [;<pn> = iif(<pn> = NIL,<valn>,<pn>)]

Enviado: 06 Dez 2007 17:32
por Mário Isa
Gostaria de saber se, em xHarbour, eu posso utilizar os .TXT para me comunicar com AcBr ?
Mário

Enviado: 06 Dez 2007 18:18
por dopi
Sim... acredito que qualquer linguagem possa...

Porem no xHarbour, usando TCP/IP fica muito mais rápido... No exemplo de Clipper / xHarbour que acompanha o ACBrMonitor vc pode usar TXT ou TCP... depende apenas de como vc inicializa o Endereço

Re: Acesso via Socket TCP/IP

Enviado: 30 Dez 2007 21:22
por lindinaldo
Boa noite


Gostaria de rodar meu sistema em Linux


Uso o harbour


Gostaria de qual versao do Linux e usada e onde tem o harbour
para Linux e como fazer para gerar o executal com varios prg..


Atenciosamente
LINDINALDO

Re: Acesso via Socket TCP/IP

Enviado: 31 Dez 2007 13:39
por sygecom
lindinaldo escreveu:GOSTARIA DE QUAL VERSAO DO LINUX E USADA
Sou iniciante ainda no mundo Linux, por falta de tempo não pude ir mais afundo ainda no LINUX, mas procure usar alguma DISTRO que já tenha o harbour compilado para a mesma, sendo assim poder FEDORA,UBUNTU e MANDRIVA, claro que pode usar outras distro, mas aconselharia para começar usando uma dessas citadas.
E ONDE TEM O HARBOUR PARA LINUX
Baixe direto do Projeto na SourceForge:
http://sourceforge.net/projects/harbour-project/
COMO FAZER PARA GERAR O EXECUTAL COM VARIOS PRG..
Use o hbmake, nos links abaixo explica como usar o HBMAKE:
http://www.caclipperwebsite.com/harbour.shtml
https://pctoledo.org/forum/viewtopic.php?t=2014

Obs: Eu toh usando o UBUNTU 7.10 Server com xharbour 1.0.0

No link abaixo tem umas dica de como usar o xHarbour no Ubuntu:
http://xhgtk.sourceforge.net/config12.html

Abraços
Leonardo Machado

Enviado: 31 Dez 2007 17:03
por hrodrigom
So uma pequena dica que espero que seja util.

Para opter o ip da maquina Windows que esta acessando o seu sistema via ssh (com o cliente PUTTY por exemplo), vc pode leer a variavel de ambiente SSH_CONNECTTION

Vc deixaria o monitor ACBR na sua estação com Windows
e no sistema q esta rodando no servidor vc se conectaria mais ou menos assim.

Código: Selecionar todos

  
cAdress := getenv('SSH_CONNECTION')
cAdress := substr(cAdress, 1, at(' ',cAdress))
cPort := '3434'

Socket := InetConnect( cAddress, Val( cPort ) )
Assim, vc nao precisa se preocupar com o IP do cliente. Mas para isto vc tem que ter acesso a esse ip, liberando o firewall.

Agora se vc esta se conectando ao servidor a travez da internet por exemplo, e nao tem acesso ao ip do cliente, vc pode criar uma VPN ou um simples tunel ssh usando o propio PUTTY. Recomendo leitura sobre este assundo o seguinte artigo http://www.guiadohardware.net/tutoriais/vpn-usando-ssh/