sexta-feira, 3 de abril de 2020


Hoje irei disponibilizar um código em advpl para verificar a similaridade de duas strings. Ele é uma adaptação que eu fiz baseado no algorítimo de Levenshtein.
Mais detalhes no link :Levenshtein distance
Basicamente ele informa quantos operações serão necessárias para deixar uma string igual a outra. Algo muito utilizado em corretores ortográficos como também em aplicações de IA em que podemos analisar a resposta dada por algum usuário em um questionário ou um Chatbot.


Por exemplo, a distância Levenshtein entre as palavras inglesas "kitten" (gato) e "sitting" (sentando-se) é 3, já que com apenas 3 edições conseguimos transformar uma palavra na outra, e não há maneira de o fazer com menos de três edições:
  • kitten
  • sitten (substituição de 'k' por 's')
  • sittin (substituição de 'e' por 'i')
  • sitting (inserção de 'g' no final)


Segue o fonte:
#INCLUDE "PROTHEUS.CH" 
#INCLUDE "RWMAKE.CH" 
#include 'tbiconn.ch'

//recebe duas strings como parâmetro e realiza a comparação entre elas usando
//o algorítimo de Levenshtein

User Function POSTRING(s,t)
Local i := 1
Local j := 1
Local sa   := {}
Local ta   := {}

//transformar string em array 
for i := 1 To len(s)
    aaDD(sa,SubStr(s,i,1))
next 
for i := 1 To len(t)
    aaDD(ta,SubStr(t,i,1))
next 


n = Len(s
m = Len(t
d = Array(n+1,m+1)

//colocando zeros nas posições do array pois n pode ter elemento nulo (nil)
for i := 1 To n+1
    for j := 1 To m+1
        d[i,j] := 0
    next j
next i 



if (n == 0)
    return m
EndIf
if (m == 0)
    return n
Endif

for i = 1 To  n + 1 
    d[i, 1] = i-1
next

for j = 1 To m + 1
    d[1, j] = j-1
next

for i := 2 To n + 1
    for j:= 2 To m + 1
        cost = iif(ta[j - 1] == sa[i - 1],0,1)
        d[i, j] = Min(Min(d[i - 1, j] + 1, d[i, j - 1] + 1),d[i - 1, j - 1] + cost)
    next j
next i 


Return  d[n+1, m+1]

terça-feira, 3 de julho de 2018

Novo Blogger da empresa ERP Consult Brasil

http://erpconsultbrasil.blogspot.com/

quarta-feira, 18 de outubro de 2017

Integração Protheus vs Arduino

Neste artigo rápido, gostaria de mostrar uma simples integração entre o ERP Protheus e o Arduino. Não irei aprofundar-me na arquitetura da plataforma arduino, mas resumidamente, ele permite uma ótima integração entre software e hardware.

Imagine poder controlar a rotação de um motor elétrico, nível de luminosidade em determinado ambiente, abrir e fechar circuitos, acionar alarmes, trabalhar com diversos sensores como de temperatura, de presença  usando o ERP Protheus. Com o arduino, isso é possível. E para começar a mostrar as possibilidades, irei iniciar com um projeto bem simples aonde uma tela em advpl terá botões que irão controlar o acendimento de leds.

Para começar, segue abaixo o código usado na IDE do Arduino:

const int LEDa = 13;
const int LEDb = 12;
const int LEDc = 11;
const int LEDd = 10;

void setup() {
  Serial.begin(9600);    //configura comunicação serial com 9600 bps
  pinMode(LEDa,OUTPUT);   //configura pino do led como saída
  pinMode(LEDb,OUTPUT);   //configura pino do led como saída
  pinMode(LEDc,OUTPUT);   //configura pino do led como saída
  pinMode(LEDd,OUTPUT);   //configura pino do led como saída
}
void loop() {
   if (Serial.available()) //se byte pronto para leitura
   {
    apagaTudo();
    switch(Serial.read())      //verifica qual caracter recebido
    {
      case 'A':                  //caso 'A'
        digitalWrite(LEDa,HIGH); //inverte estado do LED
      break;

      case 'B':                  //caso 'B'
        digitalWrite(LEDb,HIGH); //inverte estado do LED
      break;

       case 'C':                  //caso 'C'
        digitalWrite(LEDc,HIGH); //inverte estado do LED
      break;

      case 'D':                  //caso 'D'
        digitalWrite(LEDd,HIGH); //inverte estado do LED
      break;
     
    }
  }
}

void apagaTudo()
{
  digitalWrite(LEDa,LOW);
  digitalWrite(LEDb,LOW);
  digitalWrite(LEDc,LOW);
  digitalWrite(LEDd,LOW);
}



Agora, a tela Protheus que irá controlar os leds:

#INCLUDE "rwmake.ch"                                                 
#INCLUDE 'PROTHEUS.CH'
#include "topconn.ch"   
#INCLUDE 'FONT.CH'
#INCLUDE 'COLORS.CH'


User Function intARDU()  

SetPrvt("oDlg1","oBtn1","oBtn2","oBtn3","oBtn4")

oDlg1      := MSDialog():New( 092,232,225,748,"INTEGRAÇÃO PROTHEUS VS ARDUINO",,,.F.,,,,,,.T.,,,.T. )
oBtn1      := TButton():New( 012,032,"LED A",oDlg1,{|| SendMSG('A')},037,012,,,,.T.,,"",,,,.F. )
oBtn2      := TButton():New( 012,080,"LED B",oDlg1,{|| SendMSG('B')},037,012,,,,.T.,,"",,,,.F. )
oBtn3      := TButton():New( 012,128,"LED C",oDlg1,{|| SendMSG('C')},037,012,,,,.T.,,"",,,,.F. )
oBtn4      := TButton():New( 012,176,"LED E",oDlg1,{|| SendMSG('D')},037,012,,,,.T.,,"",,,,.F. )

oDlg1:Activate(,,,.T.)


Return




Static Function SendMSG(cMSG)


Local cCfg := "COM3:9600,n,8,1"
Local nH := 0


lRet       := msOpenPort(nH,cCfg)     

if(!lRet)
    Alert("Falha ao conectar com a porta serial")
    Return
EndIf 

msWrite(nH,cMSG)

Return



A tela no Protheus deverá ficar assim:



O esquema da placa ficaria assim:



Basicamente o Protheus irá se conectar com a placa Arduino usando a porta USB emulada como porta COM, por isso, o código advpl usa  msOpenPort.

Por último, o resultado:



domingo, 17 de setembro de 2017

Uma grande dor de cabeça para o desenvolvedor Advpl Protheus é a confecção de relatórios gráficos. Por não oferecer um bom ambiente de desenvolvimento, os relatórios à base do objeto TMSPrinter são construídos manualmente via código, gerando em muitos casos retrabalho, além de do fato do próprio componente em questão estar descontinuado pela TOTVS.
Uma opção para cobrir este "vazio" seria usar outras ferramentas disponíveis no mercado como o Crystal Reports ou Ireport. A primeira opção tem um custo um pouco elevado além da possibilidade de surgir problemas na integração e a exigência de cada micro ter uma ODBC criada para atender a conexão. Já o Ireport também pode apresentar problemas de integração e exige que cada micro tenha o Java instalado.

Pesando em uma solução, criei uma arquitetura simples que oferece relatórios gráficos, com ferramenta de desenvolvimento rápido além de fácil integração com o Protheus, sem a necessidade de instalar dll, executáveis ou criação de ODBC. Basta apenas compilar um fonte e pronto, os relatórios já ficam disponíveis.

A arquitetura basicamente é a seguinte:


O ambiente de desenvolvimento é bem parecida com as que temos hoje no mercado, abaixo um projeto aberto nele:


E no Protheus um exemplo de um relatório feito pela ferramenta citada:




O relatório pode conter também gráficos, imagens etc. 

Para mais informações, como valores , treinamento e implantações, basta entrar em contato pelo Skype luis.lacombe ou por e-mail : erpconsult@erpconsultbrasil.com.br







quarta-feira, 17 de junho de 2015


Olá desenvolvedores.... Publiquei um vídeo bem rápido ensinando o básico de como consumir um webservice em .net (C#) usando o Protheus. Espero que seja útil. 




domingo, 13 de julho de 2014

Pacote para desenvolvimento de integração Protheus e balança via porta serial

Estou disponibilizando um pacote para desenvolvedores advpl com o objetivo de desenvolver rdmakes de integração com balanças via comunicação serial. No vídeo http://youtu.be/28NJP7xbMpY tem uma pequena demonstração e no link  http://www.4shared.com/rar/P-ejAam9ba/Pacote_Balanca.html? disponibilizo o pacote que vem com emulador de porta COM, simulador de balança além de um rdmake de exemplo.

domingo, 9 de março de 2014

Obter endereço a partir de um cep com ADVPL

Abaixo abaixo estou disponibilizando um pequeno código que recebe um cep como parâmetro e acessa um web service, obtendo como retorno o endereço correspondente. Espero que seja útil.

#INCLUDE 'PROTHEUS.CH'
#INCLUDE 'RWMAKE.CH'
#INCLUDE 'FONT.CH'
#INCLUDE 'COLORS.CH'


User Function VerCep()

Private cBairro    := Space(100)
Private cCidade    := Space(100)
Private cLog       := Space(100)
Private cTipLog    := Space(20)
Private cUF        := Space(20)      
Private cCep       := Space(12)


SetPrvt("oDlg1","oSay1","oSay2","oSay3","oSay4","oSay5","oSay6","oGet1","oSBtn1")


oDlg1      := MSDialog():New( 088,232,316,624,"oDlg1",,,.F.,,,,,,.T.,,,.T. )
oSay1      := TSay():New( 012,012,{||"Digite o CEP:"},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,036,008)
oSay2      := TSay():New( 044,016,,oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,032,008)
oSay3      := TSay():New( 044,056,,oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,128,012)
oSay4      := TSay():New( 064,016,,oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,168,012)
oSay5      := TSay():New( 084,012,,oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,032,012)
oSay6      := TSay():New( 084,052,,oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,132,012)
oGet1      := TGet():New( 012,052,{|u| If(PCount()>0,cCep:=u,cCep)},oDlg1,060,008,'',,CLR_BLACK,CLR_WHITE,,,,.T.,"",,,.F.,.F.,,.F.,.F.,"","cCep",,)
oSBtn1     := SButton():New( 012,160,1,,oDlg1,,"", )    

oSBtn1:bLClicked := {|| LoadCEP() }

oDlg1:Activate(,,,.T.)

Return 

Static Function LoadCEP()
Local cError   := ""
Local cWarning := ""
Local aRetorno := {} 
Local cRETORNO  //obtem o xml

cRETORNO := HttpGet( 'http://republicavirtual.com.br/web_cep.php?cep='+cCep+'&formato=xml' )

if cRETORNO == nil
   MsgStop( Alert( "Servidor de CEP indisponível." ) )
else
   oScript := XmlParser( cRETORNO, "_", @cError, @cWarning )
   if oScript <> nil
      if XmlChildEx( oSCRIPT, "_WEBSERVICECEP" ) <> nil      
         if Val(oSCRIPT:_WEBSERVICECEP:_RESULTADO:TEXT) > 0
            cUF     := oSCRIPT:_WEBSERVICECEP:_UF:TEXT 
            cCidade := oSCRIPT:_WEBSERVICECEP:_CIDADE:TEXT 
            cBairro := oSCRIPT:_WEBSERVICECEP:_BAIRRO:TEXT 
            cTipLog := oSCRIPT:_WEBSERVICECEP:_TIPO_LOGRADOURO:TEXT 
            cLog    := oSCRIPT:_WEBSERVICECEP:_LOGRADOURO:TEXT 
         endif   
      endif
   endif
endif 

oSay2      := TSay():New( 044,016,{||"UF: " + cUF},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,032,008)
oSay3      := TSay():New( 044,056,{||"Cidade: " + cCidade},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,128,012)
oSay4      := TSay():New( 064,016,{||"Bairro: " + cBairro},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,168,012)
oSay5      := TSay():New( 084,012,{|| cTipLog},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,032,012)
oSay6      := TSay():New( 084,052,{|| cLog},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,132,012)      

Return


----------------------------------------------------------------------------------------------------
A aparência do programa é simples, agora é só incrementar do jeito que você quiser.