Utilizando Node.js para o controle de hardware pela WEB através do protocolo Firmata

Neste artigo falarei sobre uma aplicação muito interessante que pode ser feita utilizando-se Node.js: o controle de hardware pela WEB. A aplicação que escolhi foi o controle do estado de diversos leds conectados a um Arduino, com o qual o servidor Node.js se comunicará. É uma aplicação extremamente simples do ponto de vista do hardware, mas que servirá para ilustrar os conceitos necessários para a criação de aplicações mais complexas. O código-fonte completo da aplicação pode ser baixado do repositório no GItHub.

A Aplicação

Primeiramente, descreverei em detalhes a aplicação que será desenvolvida. Ela consistirá de dois leds, que poderão ser acendidos ou apagados pelo usuário através de uma interface WEB. Além disso, o usuário poderá monitorar o estado desses leds a qualquer momento. A mesma aplicação poderá ser utilizada por diversas pessoas, e se um outro usuário alterar o estado de um dos leds através de outra instância da aplicação, os demais usuários serão informados disso em tempo real.

A aplicação é dividida em três partes distintas:

  • Interface do Usuário – Exibe o estado dos dois leds, e permite que esse estado seja modificado. O estado dos leds é mantido atualizado com o estado físico dos mesmos. Essa camada se comunica diretamente com o servidor Node.js;
  • Servidor Node.js – Recebe as solicitações de alteração de estado dos leds, e as repassa ao Arduino. Também é responsável por avisar à camada de interface das mudanças ocorridas no estado dos leds em tempo real. Essa camada se comunica tanto com a interface quanto com a camada de Hardware;
  • Hardware – Consiste dos dois leds mais o Arduino.

A comunicação entre a interface do usuário e o servidor Node.js será feita através da biblioteca http://socket.io, e a comunicação do servidor com o Arduino será feita de maneira serial. Cada uma dessas três partes serão descritas a seguir, de maneira independente.

Interface do Usuário

A interface é bastante simples. Cada um dos leds é representado um ícone, que pode estar em preto (led apagado) ou amarelo (led aceso). Além disso, há dois botões de ação. Se um led estiver aceso, e o botão correspondente a ele for acionado, esse led será apagado; caso contrário, ele será aceso. Os nomes dos leds são referentes aos pinos do Arduino aos quais eles estão conectados fisicamente.

Interface do usuário formada por dois leds, cada um deles com um botão de ação associado.

Para a geração do HTML da página, optei por utilizar a linguagem de template jade. É uma linguagem bastante simples, que facilita a geração do HTML através de uma linguagem mais limpa, e que possui uma série de funcionalidades. Essas funcionalidades não serão detalhadas, mas o leitor que sentir necessidade é convidado a ler a documentação oficial. O código abaixo gera todo o HTML da interface.

O css presente em style.css é bastante simples, então não vou adicioná-lo ao artigo para não deixá-lo desnecessariamente comprido.

Agora, descreverei o código javascript que será responsável por fazer a comunicação entre o navegador e o servidor Node.js. Essa comunicação será feita através da biblioteca socket.io. Ela permite que uma conexão seja mantida aberta entre as duas partes da aplicação, de modo que qualquer uma delas pode enviar uma mensagem para a outra a qualquer momento.

Essa conexão é estabelecida através do código abaixo.

Nesse código, localhost é o endereço do servidor node.js, e 5555 é a porta através da qual as mensagens serão trocadas. Agora, quando um dos botões for pressionado, devemos avisar ao servidor. Isso será feito disparando um evento, que chamarei de toggle_led.

Na linha 3, disparamos o evento toggle_led. Esse evento será “escutado” pelo servidor em tempo real, e terá como parâmetro a variável led_number, que possui o número do led cujo estado deve ser invertido. Por fim, precisamos atualizar o estado dos leds na tela do usuário quando o servidor acender ou apagar algum dos leds.

Nesse caso, o servidor disparará o evento changed, e enviará como parâmetro o estado atual dos dois leds. Assim, cada um dos leds recebe a classe HTML on ou off, dependendo de ele estar aceso ou apagado. Todos os usuários que estiverem utilizando a aplicação escutarão o evento changed quando o servidor modificar o estado de um dos leds. Assim, todos eles terão em sua tela o estado atualizado dos leds.

Servidor Node.js

Apesar de se uma aplicação simples, eu optei por utilizar o framework Express. Desse modo, se eu quiser fazer algo mais complexo futuramente, não haverá grandes dificuldades. Como eu já expliquei o básico sobre esse framework em outro artigo, vou explicar aqui apenas a parte referente à aplicação deste artigo.

Primeiramente, adicione os pacotes socket.iojohnny-five à sua aplicação. O pacote socket.io já foi explicado anteriormente, e o johnny-five é quem fará a comunicação com o Arduino. Abaixo, é feita a  inicialização dos leds e da comunicação com o Arduino .

Na linha 4, devemos informar a porta serial à qual o Arduino se encontra conectado. Na linha 7, o evento ready é disparado pela variável board após a comunicação ter sido estabelecida com a placa. Por fim, após a inicialização dos leds, a função ioChanged() avisará aos usuários da aplicação que o estado dos placa mudou, disparando o evento changed para a camada de interface do usuário. Essa função será apresentada a seguir.

Para permitir a comunicação em tempo real entre o servidor e a camada de interface, devemos inicializar o pacote socket.io, como a seguir.

Assim, quando um usuário se conectar ao servidor através da porta 5555, a função a seguir será executada.

Primeiramente, verificamos se a comunicação entre o servidor e o Arduino já foi estabelecida. Em caso afirmativo, o estado dos leds é enviado para o usuário que acabou de se conectar ao servidor através do evento changed. Na linha 5, sempre que esse usuário gerar o evento toggle_led para o servidor, o estado físico do led correspondente é alterado (linha 6), e, então, todos os usuários que estejam usando a aplicação no momento são avisados disso em tempo real (linha 7).

Por fim, segue a implementação da função ioChanged().

Camada de Hardware

Muito pouco precisa ser feito na camada de hardware para que a comunicação com o servidor seja feita. O pacote johnny-five, responsável por fazer essa comunicação, utiliza o protocolo Firmata. Sendo assim, precisamos gravar um programa no Arduino que seja implemente esse protocolo. Felizmente, a IDE do Arduino já vem com um exemplo que implementa o protocolo Firmata. Assim, só precisamos gravá-lo!

Para isso, vá em File -> Examples  -> Firmata  -> StardardFirmata, como mostra a Figura abaixo.

Feito isso, basta gravar o programa no Arduino, e a comunicação estará funcionando! Agora, basta conectar os leds aos pinos 2 e 13 do Arduino, para que a aplicação esteja finalizada.

 

 

Node.js: Criando um servidor REST com o Padrão MVC utilizando o Framework Express

Olá, já faz um bom tempo que não escrevo por aqui. Estou com pouco tempo livre devido a meu projeto de mestrado. Neste post falarei sobre parte de um projeto recente que venho desenvolvendo, durante o qual precisei criar um servidor REST com Node.js.

Sou um grande fã de CakePHP, pois foi o primeiro framework para web que tive contato, e com o qual aprendi bastante. Talvez por isso, sempre que aprendo uma nova linguagem, procuro encontrar analogias com alguma parte do CakePHP que eu já conheço. Sendo assim, procurei deixar a estrutura da aplicação o mais parecida possível com o que eu utilizava com CakePHP.

obs: se você não está familiarizado com o padrão MVC, leia este artigo.

Neste projeto, a maioria dos métodos dos models utilizam o pacote Bluebird para promessas. Além disso, o banco de dados que escolhi foi o MySQL. Algumas alterações na camada demodels podem ser necessárias se você quiser utilizar outro banco de dados.

O fonte completo da aplicação pode ser baixado aqui.

Estrutura básica da aplicação

Se você já estiver acostumado com o padrão MVC, não terá dificuldades para entender a função de cada diretório da aplicação. Há um diretório para os controllers e um para osmodels, mas nenhum para as views. Optei por retornar os dados do servidor apenas no formato JSON. Caso você deseje suporte para mais formatos, pode utilizar uma camada deviews separada da dos controllers para isso.

Antes de tudo, edite o arquivo config/config.js com as configurações de acesso ao banco de dados e a porta a ser utilizada pela aplicação. Você também pode especificar a porta através da variável de ambiente PORT.

Rotas

O Framework Express já possui um sistema de rotas bastante interessante, então pouco trabalho foi preciso aqui.

Cada controller possui uma função addRestRoutes que adiciona as rotas básicas do servidor automaticamente. Essas rotas mapeiam para ações presentes na classe Controller. Cadacontroller da sua aplicação deve herdar os métodos da classe Controller.

As rotas padrões são no formato a seguir:

  • GET /blog/1: mapeia para a ação findById
  • POST /blogs/searches: mapeia para a ação search
  • POST /blogs: mapeia para a ação create
  • PUT /blog/1: mapeia para a ação edit
  • DELETE /blog/1: mapeia para a ação delete

As ações search, create e edit requerem que alguns parâmetros sejam passados no corpo da requisição.

Para a ação de busca, os parâmetros devem ser passados seguindo o formato a seguir:

Para as ações create e put, devem ser passados os dados a serem salvos no banco de dados.

Se o controller possuir alguma rota que saia deste padrão, elas podem ser adicionadas pelo método addCustomRoutes como a seguir:

Controllers

A estrutura básica para um controller é a seguir.

O arquivo acima deve se chamar CarsController.js e estar na pasta controllers.

Models

Os models precisam de algumas configurações para o correto funcionamento dos métodos da classe Model. Um model básico é apresentado a seguir.

Os principais métodos herdados da classe Model são listados abaixo.

Model.find

Realiza uma consulta ao banco de dados.

Exemplo de Uso

Parâmetros

  • conditions : array de condições no formato do pacote squel
  • limit : máximo de registros para serem retornados
  • offset : números de registros para serem pulados
  • group : cláusula SQL group by
  • recursive : nível de recursividade para buscar por registros nos models com os quais este está associado

Model.findById

Busca por um registro com determinado id. Seu único parâmetro é o id do objeto a ser buscado. Este método retorna uma promessa rejeitada se não houver registro com o id especificado.

Model.save

Cria ou atualiza um registro já existente no banco de dados.

Exemplos de Uso

Model.delete

Remove um registro do banco e dados. Seu único parâmetro é o id do registro a ser removido.

Gerando Sitemap para um Blog feito com o Framework Express para Node.js

Nesse artigo explicarei superficialmente o que são sitemaps, e mostrarei como gerá-los com um pacote já existente. Os exemplos práticos serão focados para a utilização em blogs, mas podem ser facilmente estendidos para qualquer tipo de página web. Os sitemaps gerados permanecerão em cache por 24 horas (tempo esse que pode ser modificado livremente, dependendo do volume de atualização de seu blog).

Optei por utilizar o pacote sitemap, que não é específico para Express, mas que é bastante simples de utilizar e que possui um sistema de caches interessante. Há o pacote express-sitemap, para Express, mas que funciona melhor para sites compostos por páginas estáticas. Para um blog, não encontrei muitas vantagens em utilizá-lo no lugar do pacote sitemap.

Se você já sabe o básico sobre sitemaps, a primeira seção do artigo pode ser ignorada.

Introdução aos sitemaps

Sitemap é um protocolo feito para facilitar a indexação das páginas de um site pelos mecanismos de pesquisa. Ele pode consistir de apenas um arquivo de texto, em que cada linha corresponde à URL de uma página do site que você deseje indexar.

Naturalmente, o fato de uma URL não estar no sitemap não quer dizer que ela não será exibida nas páginas de busca (se é isso o que você deseja, leia sobre robots.txt), e uma URL estar em seu sitemap não quer dizer que ela aparecerá na primeira página de nenhum mecanismo de busca.

Os sitemaps servem apenas como facilitadores, assegurando que nenhuma página de seu site deixe de ser analisada pelos mecanismos de pesquisa, e permitindo que você diga, por exemplo, quais páginas considera mais importantes em seu site.

A forma mais comum de se utilizar sitemaps é através de um arquivo XML, que contém, entre outras informações, a última vez em que cada página foi atualizada e, em média, quão frequentes são essas atualizações.

Acima, a página http://www.example.com/ foi modificada pela última vez em 01/01/2015, espera-se que seja modificada mensalmente, e possui prioridade 0.8 (numa escala de 0 a 1). Uma prioridade maior não garante que sua página aparecerá mais bem posicionada nas buscas, mas diz quais páginas, dentro de seu site, você considera mais importantes.

Instalação e Configuração do Pacote Sitemap

Para instalar o pacote, adicione sitemap às dependências de seu arquivo package.json, ou execute o comando

A seguir, crie o arquivo routessitemap.js, e adicione-o a seu objeto app.

Você pode, então, criar seu objeto sitemap como a seguir.

Acesse seusite/sitemap.xml, e você verá o XML do sitemap, ainda sem a URL de nenhuma página.

Adicionando seus Posts ao Sitemap

Agora, você deve obter as URLs de seu blog, para adicioná-las ao objeto sm. Nem todas as URLs precisam ser adicionadas, mas apenas aquelas que possuam conteúdo relevante. Por exemplo, URLs de paginação ou de filtros, em geral, não possuem conteúdo novo: são apenas formas de facilitar a navegação dentro do site, para que o usuário encontre o que deseja.

Sendo assim, optei por adicionar ao sitemap apenas as URLs referentes aos posts do blog.

O método sm.toXML() verifica há quanto tempo o último XML foi gerado, para determinar se é preciso renovar o XML ou se o último gerado ainda é válido. Isso trás um ganho considerável no tempo de geração do mesmo, se seu sitemap possuir muitas páginas.

Caso você prefira utilizar o pacote express-sitemap, poucas alterações teriam de ser efetuadas. A principal é referente ao cache, que não é gerenciado pelo pacote. Assim, você poderia, por exemplo, utilizar cron jobs para gerar o XML, e salvar em public/sitemap.xml a intervalos regulares, ou salvar numa variável o timestamp da última vez que o sitemap foi gerado.

Jade: Criando Blocos Reutilizáveis com Mixins

Os benefícios da modularização já foram amplamente estudados na Engenharia de Software, e não são o foco deste artigo. Nele explicarei apenas o que for relevante do ponto de vista da implementação. Caso esteja interessado, consulte também a documentação oficial (em inglês) sobre como implementar herança de views.

Todos os exemplos utilizados neste artigo foram retirados da documentação oficial (em inglês).

Mixins

Mixins são blocos reutilizáveis de código, permitindo uma melhor organização de nossas views.

Primeiramente, vejamos um exemplo simples, que ilustra a declaração e o uso de mixins.

O código Jade abaixo

gera o HTML

Simples, não? O mixin list pode ser utilizado em qualquer arquivo .jade, desde que o arquivo de sua declaração seja devidamente incluído.

Passagem de parâmetros

Vejamos, agora, um exemplo um pouco mais útil, em que o mixin recebe parâmetros para gerar saídas customizadas.

gera o HTML

Blocos

Além disso, mixins podem receber blocos como parâmetro, para produzirem parte da (ou toda a) saída.

gera o HTML

Atributos Nomeados

Também é possível utilizar atributos nomeados, como mostra o exemplo abaixo.

produzindo o HTML

Por padrão, os atributos são escapados durante a chamada da função. Assim, eles devem ser utilizados no mixin em conjunto com o operador !, para evitar que sejam escapados duas vezes.

Número Deconhecido de Parâmetros

Por fim, ainda é possível utilizar mixins que recebam um número desconhecido de parâmetros.

O código Jade abaixo

produz o HTML

Introdução ao Framework Express

Express é um framework para node.js para a criação de aplicações web. Seu foco está, principalmente, na utilização de rotas para redirecionar cada requisição feita às funções corretas.

Uma mesma requisição pode ser atendida por várias funções, denominadas middlewares, que podem, por exemplo, manipular os dados recebidos via post para que sejam apresentados de maneira mais tratável aos demais middlewares.

Neste post explicarei como instalar o framework, e darei mais detalhes sobre o que são middlewares e como eles funcionam. Por fim, listarei alguns middlewares que considero bastante úteis.

Instalação

Inicialmente, execute o comando

Isso instalará um gerador de projetos próprio do express. A seguir, digite

Isso criará um diretório chamado myapp, com um aplicativo já pré-configurado para utilizar as funcionalidades básicas do express. Além disso, toda a estrutura de diretórios também será criada, incluindo uma pasta pública para seus assets.

Para iniciar seu servidor, digite

Veja que o código básico da sua aplicação fica no arquivo app.js.

Middlewares

Toda conexão feita ao servidor deve ser tratada por um ou mais middlewares, desde uma requisição para obtenção de algum recurso num servidor REST até uma simples requisição para baixar o favicon do site.

Cada middleware deve registrar-se no objeto do tipo express, normalmente denominadoapp, informando quais tipos de requisição deseja tratar. Opcionalmente, o middleware pode escolher receber todas as requisições feitas. Isso é feito através do método app.use (veja a documentação aqui).

A forma mais simples de se utilizar o método use é

Esse trecho de código diz ao objeto app que toda requisição feita a path deve ser tratada pela função middleware. O parâmetro path é opcional, e, se omitido, é assumido como sendo ‘/’, o que fará com que a função middleware seja chamada para atender todas as requisições feitas ao servidor.

Os parâmetros req e res possuem, respectivamente, os dados da requisição feita ao servidor e da resposta que será enviada. next é uma função que diz ao objeto app que outrosmiddlewares devem ser executados para terminar o processamento da requisição.

Vejamos alguns exemplos:

O código acima busca por usuários com id req.params.id, e retorna seus dados no formato JSON. Podemos melhorá-lo para aceitar apenas ids numéricos fazendoapp.use('/users/:id([0-9]{1,})').

No blog, utilizei o código abaixo para liberar acesso á área interna.

app.js

routes/admin.js

O exemplo acima ilustra como podemos dividir as rotas em arquivos diferentes, para melhorar a organização do código. A função router.all diz que todos os tipos de requisição devem ser tratados pelo middleware isLogged.

Se o usuário que estiver tentando acessar o admin estiver logado, a função next é executada, e os demais middlewares podem prover o recurso solicitado. Caso contrário, o usuário é redirecionado para a tela de login.

Os principais middlewares que utilizei no blog foram

  1. body-parser – parser para os dados enviados no corpo da requisição. utilizo este middleware para facilitar o acesso aos dados enviados via POST ou PUT;
  2. less-middleware – Compilador para LESS, esse middleware intercepta todas as requisições feitas a arquivos .css, procura pelos arquivos .less correspondentes e os compila, caso tenham sido alterados desde a última compilação;
  3. express-morgan – gera logs de acessos de todas as requisições http feitas. esses logs podem ser enviados para o console ou para um arquivo de texto qualquer.;
  4. express-session como o nome diz, esse middleware é responsável por tratar as sessões dos usuários. Ele não armazena as sessões por si próprio, mas necessita receber como parâmetro algum objeto capaz de fazer esse armazenamento. Cada middlewareexecutado depois dele possuirá acesso direto à sessão do usuário através do objetoreq.session.

Num post futuro espero explicar com mais detalhes cada um desses middlewares. Até a próxima ;)

Autenticação com Node.js e Express

A autenticação é uma parte muito importante de praticamente qualquer aplicação. Esse post explica como autenticar usuários num servidor Node.js, utilizando o framework Express, e armazenando as sessões com Redis.

Configurando a Sessão

Para autenticar usuários, devemos, antes, configurar corretamente a sessão do Express. Para isso, primeiro, instale o pacote express_session através do comando

A seguir, você deve configurar o pacote instalado, como abaixo.

Dessa forma, quando uma requisição estiver sendo atendida, as informações da sessão pode ser acessadas (ou alteradas) por meio do objeto req.session.

Tentativa de Login

Assim, a rotina de login do blog ficou como abaixo.

 

Para os dados enviados via POST possam ser acessados da forma acima, devemos utilizar o pacote body-parser, adicionando as linhas

 

à rotina de inicialização do Express.

Protegendo a senha do Usuário

Muito já foi discutido sobre o porquê de criptografar todas as senhas salvas no banco de dados. Em resumo, se alguém mal intencionado tiver acesso ao banco de dados, ele, no mínimo, terá muito trabalho para descobrir as senhas cadastradas se elas estiverem criptografadas. Como muitas pessoas utilizam as mesmas senhas em vários serviços, isso é muito importante.

Para a criptografia, utilizei o pacote bcrypt. É uma boa prática utilizar uma string de salt para cada usuário. Isso se deve ao fato de que muitos usuários utilizam senhas iguais, como12345678 ou password. Assim, se todos eles utilizarem a mesma string de salt, um usuário com acesso ao banco de dados poderia procurar por senhas repetidas e fazer algumas tentativas com senhas comuns para recuperar as senhas originais.

Para utilizar o bcrypt no windows, precisei instalar o Visual Studio. Uma versão gratuita pode ser baixada aqui.

Assim, minha função de login consiste dos seguintes passos:

  1. Verifica se há algum usuário com o e-mail informado pelo usuário;
  2. Obtém a string de salt desse usuário;
  3. Criptografa a senha informada pelo usuário com o salt obtido;
  4. Verifica se essa senha pertence à conta correspondente ao e-mail informado.

A implementação da rotina segue abaixo.