Uma das formas mais interessantes de controlar um circuito a distância é por aplicativo. Portanto, vamos aprender a criar um aplicativo simples que comunica com o NodeMcu.
Na aula anterior, aprendemos a fazer requisições GET e POST em domínios na internet.
Aplicativo
Meu objetivo é ensinar a fazer um aplicativo que seja o mais simples possível, apenas para mostrar qual o caminho para aplicações que envolvam o NodeMcu e aplicativos Android. Sendo assim, vou utilizar a plataforma do AppInventor para criar um aplicativo bem básico.
Em outro post, já mostrei um pouco sobre o AppInventor ensinando a criar um aplicativo para comunicar com um módulo Bluetooth HC-05. O primeiro passo é acessar o site e fazer login.
Enfim, a ideia deste post é criar um aplicativo para ligar/desligar dois LEDs e também para exibir o estado deles (se cada um está aceso ou não). Com isso, cobrimos a parte de envio e recebimento de informações entre o NodeMcu e o aplicativo.
Interface
Componentes principais
Para o aplicativo proposto, vamos precisar de:
- 2 botões (1 para cada LED), sendo que cada botão comuta o estado atual do LED.
- Uma caixa de texto para inserir o IP do NodeMcu.
- É por meio do IP que mandaremos as informações.
- Um botão para definir o IP inserido na caixa de texto.
- Alguns Labels para criar textos.
- Adicionalmente, resolvi colocar uma imagem para melhorar o visual do aplicativo.
A forma como posicionei cada componente está mostrada abaixo:
A forma como os itens acima estão listados está mostrada na imagem abaixo:
Dicas
Para adicionar a imagem, veja o passo a passo mostrado abaixo:
Primeiro, faça upload do arquivo desejado e depois selecione ele no componente de imagem. Por último, ajuste a largura e altura da imagem. Os componentes da imagem acima não são os mesmo utilizados no projeto deste post.
Para centralizar os componentes no meio da tela, você deve arrastar os componentes para dentro de um outro chamado “HorizontalArrangement” (ou “Organização Horizontal” em português). As configurações dele, devem ficar igual a imagem abaixo:
Na imagem acima, a largura (Width) e o alinhamento horizontal foram alterados. Os componentes da imagem acima não são os mesmo utilizados no projeto deste post.
Por fim, para colocar dois elementos lado a lado, como é o caso do escrito “IP atual” e a caixa de texto, você deve fazer a mesma coisa que foi descrito acima. Utilizando um HorizontalArrangement, você coloca os componentes dentro dele e, entre os dois, você adiciona um Label sem texto.
O Label vazio serve para criar um espaço entre os dois elementos. Com isso, basta ajustar a largura (Width) do Label vazio para aumentar ou diminuir o espaço entre os dois outros componentes.
Componente da comunicação
Um outro elemento muito importante é o de comunicação, chamado ‘Web’. Portanto, encontre ele na paleta de componentes e arraste ao projeto.
Como ele não é um elemento visível, ele irá aparecer no AppInventor apenas abaixo da tela:
Com a interface pronta, podemos passar para a programação do nosso aplicativo.
Programação
A programação foi feita o mais simples possível para facilitar o entendimento do processo todo. Entretanto, é possível criar diversas funcionalidades diferentes para deixar o aplicativo mais completo e inteligente.
Não pretendo mostrar o passo a passo de como encontrar cada componente da programação. Sendo assim, basta procurar, na paleta de blocos, os componentes que mostrarei nas imagens. Dar uma lida neste post antes, talvez ajude neste ponto.
Inicialização
Na inicialização do aplicativo, precisamos criar uma variável para guardar o IP do NodeMcu. Além disso, é interessante definir o texto da caixa de texto do IP atual como sendo o IP configurado a princípio. O IP inicial pode ser vazio, mas, como rodei os testes várias vezes, gravei o valor do IP e já deixei ele definido nesta parte. Veja a programação:
Repare que a variável IP é iniciada com um “http://” e a caixa de texto contém apenas o IP sem o “http://”. Fiz isso, porque o módulo web precisa do IP no formato “http://XXX.XXX.XX.XX” (endereço web) e decidi deixar a caixa de texto sem o “http://” para ficar mais fácil de digitar. A falta do “http://” será compensada no tópico abaixo.
Trocando o IP
Agora, precisamos trocar o IP utilizado na comunicação pelo IP que foi digitado na caixa de texto. Para fazer isso, basta mudar o valor da variável IP que criamos no tópico acima quando o botão “Definir IP” for pressionado. Mas lembrando que precisamos adicionar o “http://” antes do texto digitado. Com isso, temos:
Botões dos LEDs
O funcionamento do acionamento dos LEDs vai ser praticamente igual nós vimos nas aulas anteriores. Iremos mandar uma requisição para o NodeMcu com um certo parâmetro. Para ler mais a respeito das requisições, veja a aula 7.
O parâmetro que usarei para acionar cada led será apenas o nome dele (led1 para o 1º LED e led2 para o 2º LED). Portanto, enviando o parâmetro ‘led1’, o NodeMcu irá reconhecer esse texto e irá comutar o valor do 1º LED. Para mandar um certo parâmetro, basta adicionar ao IP uma barra com o parâmetro (XXX.XXX.XX.XX/parâmetro). Veja um exemplo da aula 7 abaixo:
No módulo ‘Web’ do AppInventor, nós, primeiro, mudamos a URL (endereço) do módulo, para então fazer a requisição em cima desta URL. A requisição que o módulo ‘Web’ aceita é a GET. Veja os blocos de código utilizados para os botões de cada LED:
No caso do 1º LED, alteramos a URL para “http://192.168.0.7/led1” (exemplificando com o meu IP). Dessa forma, o NodeMcu irá receber a requisição com a URL com o ‘/led1’ e poderá processar o texto para fazer o acionamento do LED. Veremos isso mais à frente.
Lendo estado dos LEDs
Para ler o estado dos LEDs faremos o mesmo procedimento acima, mandaremos uma requisição para o NodeMcu. E, a partir desta requisição, o NodeMcu irá retornar um texto com o valor de cada LED.
O primeiro passo é fazer a requisição, e, para isso, usarei o parâmetro ‘estados’. Os blocos de código para o botão de receber o estado são os mesmos do acionamento dos LEDs:
A diferença aqui é que a URL agora é “http://192.168.0.7/estados”. Feito isso, precisamos criar um bloco para processar os dados recebidos pelo aplicativo. Existe um bloco de código do próprio módulo ‘Web’ para isso, chamado “when Web.GotText”.
Com esse bloco, iremos testar se a resposta recebida contém o texto “LED1” para, então, mudar o texto do Label que mostra o estado dos LEDs.
Isso é feito pois o NodeMcu retorna uma mensagem tanto ao pressionamos o botão de acionar os LEDs, quanto ao pressionamos o botão de receber o estado deles. Logo, devemos exibir o estado dos LEDs apenas quando a mensagem recebida conter algo que tenha a ver com o estado dos LEDs. Para isso, escolhi o texto “LED1” mesmo.
Veja o código deste procedimento abaixo:
Se o conteúdo da resposta tiver o texto “LED1”, o texto do Label “Resposta” é difinido como todo o conteúdo da resposta. O conteúdo da resposta virá no formato “LED1: 0 – LED2: 0”, sendo que o 0 é o estado do LED para apagado e 1 para aceso.
Resultado
O último passo é construir o ‘apk’ do aplicativo e instalá-lo no celular. Fiz isso indo em Build->App (save .apk to my computer), e depois transferi o arquivo para o celular. O aplicativo funcionando pode ser visto abaixo (na imagem o código do NodeMcu já estava funcionando também):
NodeMcu
Vamos então ao ponto de como integrar o aplicativo desenvolvido com o NodeMcu.
Circuito
Para o exemplo dado, em que temos dois LEDs, o circuito utilizado foi:
Os dois LEDs estão ligados em série com um resistor (220Ω). Além disso, o primeiro LED está ligado no pino D1 e o segundo no pino D2.
Programação
A programação para comunicar com o aplicativo é a mesma que a de criar um web server, com a diferença que não precisamos enviar uma página em ‘html’ mais. Portanto, para ver essa parte mais detalhada, recomendo ler a aula 7.
Só relembrando, a criação do web server se dá no seguinte formato:
1 2 3 4 5 6 7 8 9 10 | srv = net.createServer(net.TCP) srv:listen(80, function(conn) conn:on("receive", function(conn, payload) --Comandos conn:on("sent", function(conn) conn:close() end) -- Finaliza a comunicação end) end) |
Reconhecendo parâmetros recebidos
O parâmetro ‘payload’ será a mensagem recebida pelo NodeMcu. Sendo assim, devemos usar ele para verificar se nossos parâmetros (/led1, ou /led2 ou /estados) foram recebidos. A forma como fiz isso está mostrada abaixo:
1 2 3 | if string.find(payload,"led1") ~=nil then gpio.write(led1, 1-gpio.read(led1)) -- Comuta o estado do LED end |
Então, se existe o texto “led1” na mensagem, comutamos o estado do LED.
Resposta do NodeMcu
Como o aplicativo está fazendo uma requisição, ele precisa receber uma resposta indicando que a comunicação foi bem sucedida. Para isso, basta enviar o código “HTTP/1.1 200 OK\n\n”:
1 | conn:send("HTTP/1.1 200 OK\n\n"); |
Estado dos LEDs
Quando a mensagem recebida tiver o parâmetro “estados”, precisamos retornar o estado dos LEDs. Novamente, devemos verificar se, na mensagem recebida, existe o parâmetro “estados”, para então enviar a mensagem com o estado dos LEDs.
1 2 3 4 5 6 7 8 9 | if string.find(payload,"estados") ~=nil then -- Envia o estado de cada LED no formato: -- LED1: 0 ou 1 - LED2: 0 ou 1 conn:send("LED1: " .. gpio.read(led1) .. " - LED2: " .. gpio.read(led2) .. "\n\n"); end |
Código completo
Leia os comentários para ter um melhor entendimento do programa.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | wifi.setmode(wifi.STATION) wifi.sta.config {ssid="NOME_DO_SEU_WI-FI", pwd="SENHA_DO_WI-FI"} -- Define os pinos de cada LED led1 = 1 led2 = 2 -- Define os LEDs como saída gpio.mode(led1,gpio.OUTPUT) gpio.mode(led2,gpio.OUTPUT) tmr.alarm(0, 1000, 1, function() --Aguarda conectar na rede if wifi.sta.getip() == nil then print("Conectando à rede...\n") else ip=wifi.sta.getip() print("IP: ",ip) tmr.stop(0) end end) srv = net.createServer(net.TCP) srv:listen(80, function(conn) conn:on("receive", function(conn, payload) print(payload) -- Imprime os dados recebidos do servidor -- Verifica se na mensagem recebida existe o parâmetro led1 -- Este é o caso da URL ter o parâmetro /led1 if string.find(payload,"led1") ~=nil then gpio.write(led1, 1-gpio.read(led1)) -- Comuta o estado do LED end -- Verifica se na mensagem recebida existe o parâmetro led2 -- Este é o caso da URL ter o parâmetro /led2 if string.find(payload,"led2") ~=nil then gpio.write(led2, 1-gpio.read(led2)) -- Comuta o estado do LED end -- Envia o status de OK (sucesso na comunicação) conn:send("HTTP/1.1 200 OK\n\n"); -- Verifica se na mensagem recebida existe o parâmetro estados -- Este é o caso da URL ter o parâmetro /estados if string.find(payload,"estados") ~=nil then -- Envia o estado de cada LED no formato: -- LED1: 0 ou 1 - LED2: 0 ou 1 conn:send("LED1: " .. gpio.read(led1) .. " - LED2: " .. gpio.read(led2) .. "\n\n"); end conn:on("sent", function(conn) conn:close() end) -- Finaliza a comunicação end) end) |
Resultados finais
Depois de instalar o aplicativo que criamos e rodar o código no NodeMcu, devemos esperar ele nos retornar o seu IP. Pois é esse IP que deveremos digitar no aplicativo para controlar o NodeMcu por ele. Veja o resultado que obtive logo após rodar o código no NodeMcu:
Sabendo o IP, basta ir no aplicativo, inserir ele na caixa de texto e clicar em “Definir IP”:
O último passo é testar o aplicativo e ver se está tudo funcionando. É possível acompanhar o monitor de mensagens do NodeMcu para ver como as mensagens estão sendo recebidas. Clicando nos botões de acionar os LEDs e no de receber o estado deles, as mensagens chegaram ao NodeMcu corretamente:
É possível ver o parâmetro de cada uma delas, além de algumas informações adicionais, como o dispositivo que transmitiu as mensagens (Lenovo) e a versão Android instalada nele (6.0.1).
Enfim, com essa base de como criar a comunicação entre um aplicativo e o NodeMcu, você deve ser capaz de criar aplicações mais interessantes e complexas. Por exemplo, controlar as lâmpadas de sua casa por meio de um aplicativo.
Boa noite primeiramente parabens pelo seu ensinamente consegui fzr o app atraves do seu explicativo funcionou corretamente ficou show…
Será q vc consegue me dar uma dica de como fzr para eu acessar este aplicativo por uma rede externa jaá liberei a porta no roteador liberei tbm no firewall do windows fiz o teste de porta aberta esta aberta registrei conta no NO-IP CONSEGUE ME DAR UMA AJUDA POR FAVOR?
Boa noite e muito obrigado! Não garanto que o que eu vou falar vai funcionar, pois não cheguei a testar. As instruções que vou falar vem deste link.
O primeiro passo você já fez, que é: abrir a porta do servidor do NodeMcu no modem (a porta é igual a 80 pelo código que está no post). O IP que você deve utilizar para abrir a porta é o IP que você encontra procurando no Google “meu ip“. Além disto, este IP deve conter a porta do servidor. Portanto, ele ficaria assim: “xxx.xxx.xx.xx:80”. O processo todo é conhecido como “port forward”.
Por fim, basta acessar o servidor utilizando o ip “xxx.xxx.xx.xx:80”, sendo que o “xxx.xxx.xx.xx” é o IP que você encontra no Google procurando “meu ip“.
Neste processo, não é necessário desativar o firewall do windows, já que o firewall protege o seu computador e o NodeMcu está externo à ele.
Se este processo não funcionar, tem este vídeo aqui, que ensina como fazer isto, mas utilizando o site NO-IP que você mencionou.
Enfim, espero que dê certo. Se funcionar dê um feedback.
Olá, parabéns pelo trabalho! Gostaria de saber se com o app instalado no celular é possível controlar os leds ou qualquer outra saída que tiver sido feita e incluída no app de qualquer lugar? Tipo se vc está no trabalho com o 4g e enviar o comando no app?
Obrigado!
Olá, Jonathan. Obrigado! É possível sim e existem duas formas de se fazer isto:
1 – Abrir a porta do seu modem. No caso, você precisaria mexer nas configurações do seu modem para permitir acesso externo ao Webserver do NodeMcu. Aqui tem um tutorial em inglês.
2 – Ao invés de criar um Webserver com o NodeMcu, você pode fazer ele mandar e receber dados de um servidor externo. Um exemplo de servidor é o Firebase, mas nunca cheguei a mexer com ele ou outro para te dar um melhor direcionamento.