• Nenhum resultado encontrado

3 Componentes e Arquiteturas

3.2 Arquiteturas

3.2.4 NodeMcu + ThingSpeak (usando Lua)

A partir de agora, as duas últimas arquiteturas passam a usar o kit de desenvolvi- mento NodeMcu, que vem a ser um Esp8266 rodando o firmware Lua. Para seguir nesta configuração é necessário gravar o firmware Lua no Esp8266, esse processo é descrito com detalhes no Apêndice A. Toda programação será feita usando a linguagem Lua com o auxílio da IDE Esplorer, o Apêndice B descreve as funcionalidades da IDE. O esquema eletrônico é o mesmo da Figura 36.

O código desta arquitetura será composto por cinco arquivos: • init.lua

• crendeciais.lua • tabelas.lua • conecta_wifi.lua • thingspeak_http.lua

Estes arquivos podem ser chamados de módulos. A aplicação poderia ser escrita em apenas um arquivo, mas, a modularização será importante para mostrar alguns deta - lhes da programação Lua. O NodeMc ao iniciar, procura por um arquivo que se chama init.lua. Se ele for encontrado será então executado, se ele não existir, o NodeMcu exibirá o prompt de linha de comando e ficará aguardando que algo seja digitado. É através do init.lua que a aplicação pode ser executada automaticamente. O objetivo do init.lua é dar o start na aplicação principal.

O Código 16 mostra a pequena quantidade de linhas do init.lua. Ele imprime no ter- minal a mensagem dizendo que a aplicação será iniciada em 3 segundos, na linha 5, a função delay do objeto tmr, que recebe como parâmetro o tempo em microsegundos, pau- sa o NodeMcu por 3 segundos. A função tmr.delay() é muito semelhante à função delay da biblioteca Arduino, só que seu uso no ambiente Lua é desencorajado, pois essa função pára completamente o funcionamento do NodeMcu e como já foi visto, o firmware Lua é assíncrono e baseado em eventos, portanto, a função tmr.delay() bloqueia o NodeMcu prejudicando a sua resposta assíncrona aos eventos. Essa função só é usada no init.lua por dois motivos: o primeiro é que a aplicação principal ainda não está em execução, en- tão, não há problema nesse pequeno bloqueio, o segundo motivo é que essa pausa de 3

segundos permite que o arquivo init.lua seja removido através do comando no prompt fi- le.remove(“init.lua”), caso haja a necessidade de reprogramar o NodeMcu. Na prática isso significa que, se não houver essa pequena pausa, o init.lua iniciará e rapidamente chama- rá a aplicação principal. Assim, não será mais possível se conectar ao NodeMcu a fim de programá-lo, somente será possível acessá-lo se o firmware for regravado e com a opção

“yes, wipes all data” selecionada (ver ilustração na Figura 71), o que apagará completa-

mente a memória flash e com isso o init.lua.

A linha 7 executa o comando dofile(“conecta_wifi”) que executa o módulo conecta_wifi. A função dofile() também funciona como um comando de importação, seme- lhante à diretiva include da linguagem C++. Se o módulo tiver apenas declarações de vari- áveis, de funções, de estruturas de dados, o dofile() chama o módulo e todas essas variá - veis e funções passam a estar disponíveis. Agora, se o módulo for uma sequência de co- mandos, então esses comandos serão executados por dofile().

O próximo o módulo (Código 17) se chama credenciais.lua. Ele tem uma tabela (li- nha 3) e nas linhas 4 e 5 são criados dois índices para essa tabela e seus respectivos va - lores associados. O indíce ssid e o pwd representam o ssid da rede e sua senha. Tabelas em Lua são arrays associativos implementados eficientemente como uma combinação de array e hash (tabela de dispersão) e podem ter qualquer valor como índice menos nil (sem valor em Lua), podem haver inclusive índices negativos. Esse módulo será importa- do mais em frente e o uso da tabela ficará mais claro.

O módulo tabelas.lua (Código 18) é semelhante ao módulo anterior, sua função é apenas criar tabelas que serão usadas em outros módulos. São criadas três tabelas, uma com os modos do WiFi, outra com os estados da conexão WiFi e a terceira com os moti- vos de erros com o MQTT broker. O código mostra que, em Lua, há mais de uma maneira de criar uma tabela e declarar seus índices e valores associados. É importante destacar a presença de índices negativos (linhas 21 à 25), uma característica da linguagem Lua.

O Código 19, referente ao módulo de nome conecta_wifi.lua é chamado pelo módu- lo init.lua. O seu início importa os já conhecidos módulos tabela.lua e crendenciais.lua. A linha 7 coloca o WiFi no modo station, o que significa que o NodeMcu será capaz de se

Código 18: Módulo tabela.lua Código 17: Módulo credenciais.lua

conectar a um ponto de acesso. A linha 8 configura o ssid e senha passando como parâ- metro a tabela config que foi criada dentro do módulo credenciais.lua. A linha 12 usa o ob - jeto tmr (timer), o mesmo que foi usado no módulo init.lua, só que agora ele é usado de uma maneira bem interessante.

O NoceMcu possui 7 timers numerados de 0 à 6. Eles podem funcionar de três mo - dos:

• tmr.ALARM_SINGLE – Que dispara apenas uma vez e não necessita da função tmr.unregister().

• tmr.ALARM_SEMI – Que dispara uma vez mas pode ser reiniciada pela função tmr.start().

• tmr.ALARM_AUTO – Que repete automaticamente.

Para programar os timers usa-se a função tmr.alarm() e ela recebe os parâmetros id (de 0 à 6), intervalo em milisegundos, modo, func(). O id é o número do timer utilizado, o intervalo de tempo é o tempo em que o timer vai esperar para disparar, o modo é um dos três citados anteriormente, e a função é uma função que será executada pelo timer no intervalo determinado. Para o timer, pode ser passada uma função (com nome) definida em alguma parte do módulo ou pode ser usada uma função anônima que é definida den - tro do parâmentro função de tmr.alarm().

Na linha 12 (Código 19) pode-se ver que o timer utilizado é o 2 e está configurado assim: intervalo de tempo de 1 segundo, modo automático (tmr.ALARM_AUTO) e que re- cebe uma função anônima para ser executada periodicamente.

O bloco dessa função vai da linha 13 à 26. Na linha 13 verifica-se se a placa tem um IP, se esse valor for nil então será impresso no monitor serial o estado do WiFI (base- ado na tabela estado_wifi) e a funcão será reiniciada no segundo seguinte. Mas, se o No- deMcu tiver um IP válido a função então imprimirá o estado da rede (conectado), o ende- reço de IP e o MAC adress do NodeMcu. Na linha 23 o timer é desativado e o seu id fica liberado para a programação de outro timer. Na linha 24 o módulo principal é então carre- gado e executado.

As linhas de 9 à 12 (Código 20) declaram variáveis já conhecidas de arquite- turas anteriores e cujo os nomes são autoexplicativos. A linha 15 faz uma primeira leitura do sensor que retorna um tupla e as variáveis recebem os valores na devida ordem.

Na linha 41 (Código 21) o timer 1 é registrado para funcionar em intervalos de 15 segundos no modo de repetição automática e como corpo de sua função anônima ele

executa a linha 43, que chama a função postThingSpeak(), que será explicada mais em frente, e na linha 44 chama a função le_DHT11() que faz mais uma leitura do sensor. O ti- mer será disparado novamente nos próximos 15 segundos até que a aplicação seja inter- rompida.

A linha 17 do Código 22 declara a função. Na linha 18 um objeto cliente HTTP é cri- ado, na linha 19 é definida uma função callback para o evento receive do cliente. Assim que o cliente receber alguma informação o corpo da função callback será executado. A função recebe dois parâmetros, o primeiro é o próprio objeto cliente e o segundo é uma string que guardará a resposta enviada pelo servidor. Dentro do corpo da callback a string com a resposta é varrida (função string.find) em busca de uma indicação de sucesso da parte do servidor, a string buscada é “Status: 200 OK” que indica o sucesso na resposta do servidor. Em caso de sucesso uma mensagem de OK é impressa no monitor serial, caso contrário nada ocorre.

Na linha 26 uma nova função callback é definida, desta vez para o evento connecti- on que é disparado quando o cliente se conecta ao servidor. Essa função tem o mesmo formato da anterior, ou seja, recebe primeiro o objeto cliente e depois uma string que ar- mazena a resposta do servidor. Essa string é opcional, como não há interesse na string de resposta, ela não será utilizada.

Na linha 29, o método send do objeto cliente envia a string com a requisição HTTP contendo: a api de escrita, temperatura e umidade no formato adequado. Isso já foi mos - trado anteriormente. A concatenação de strings em Lua é feita usando .. (dois pontos se - guidos).

Por último, ainda dentro da função postThingSpeak(), o método connect do objeto cliente é chamado tendo como parâmetros a porta padrão para serviços HTTP (porta 80) e a string api.thingspeak.com. A partir desse comando um evento connection ocorre, o cli- ente então responde ao evento enviando a requisição HTTP.

O servidor responde e um outro evento ocorre, só que desta vez é um evento recei- ve. Então, o cliente responde a este evento executando o código que verifica o conteúdo da resposta. E assim, o código vai executando indefinidamente em intervalos de 15 se- gundos.

Código 22: Postando no ThingSpeak - Cliente HTTP Código 21: Configurando o timer para o envio de dados