Académique Documents
Professionnel Documents
Culture Documents
real
Wilson Mendes
Esse livro está à venda em http://leanpub.com/nodebots-javascript-e-robotica-no-mundo-real
Esse é um livro Leanpub. A Leanpub dá poderes aos autores e editores a partir do processo de
Publicação Lean. Publicação Lean é a ação de publicar um ebook em desenvolvimento com
ferramentas leves e muitas iterações para conseguir feedbacks dos leitores, pivotar até que você
tenha o livro ideal e então conseguir tração.
Sobre o autor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Agradecimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Nodebots e microcontroladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
O que são nodebots? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Microcontroladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
NodeJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Gerenciando dependências com o NPM . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Firmata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Johnny Five . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Apêndice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Protoboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Piezo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Resistores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
LED (Light-emitting diode) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Sensores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Condutor de Proteção (Fio Terra ou Ground) . . . . . . . . . . . . . . . . . . . . . . . . . 89
Fios de condução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Botão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Próximos passos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Sobre o autor
GDE (Google Developer Expert) AngularJS, GDG Salvador organizer, apaixonado por tecnologia e
ativo em comunidades com foco em desenvolvimento web, incluindo AngularJS, JavaScript, HTML5,
CSS3, workflow, web performance, segurança e Internet of things. Participa na organização de
eventos, palestra em conferências no Brasil e em outros países e contribui para projetos opensource
como Oh-My-Zsh1 , AngularJS2 , Webpack3 , dentre outros.
1
https://github.com/robbyrussell/oh-my-zsh
2
https://github.com/angular
3
https://github.com/webpack
Introdução
Esta parte do livro é direcionada a todos que desejam dar os primeiros passos sobre Nodebots ou que
tem interesse em aprofundar-se em alguns conceitos que são pouco demonstrados sobre o assunto.
Serão mostrados conteúdos com sensores simples e de baixo custo, porém relacionando os sensores
com integrações reais de uma aplicação nodebots, como integração entre API’s externas a partir de
eventos leitura de alguns dados de sensores, dentre outros.
Além disto o livro aborda tópicos importantes nos quesitos de testes, mostrando boas práticas para
a cobertura de testes e como testar com uma boa qualidade e performático, com integrações em
serviços externos para automatização de tarefas de validação de qualidade de código e build.
Outro ponto abordado é o quesito de evolução da aplicação com foco na arquitetura. Como utilizar
padrões de arquitetura de software em qualquer tipo de projeto e como tirar proveito de cada um
deles aplicando no seu sistema.
Agradecimentos
Gostaria de agradecer inicialmente a minha mãe (que fez o papel de mãe e pai por muitas vezes),
essa pessoa maravilhosa que me ensinou muitos dos valores e que levo comigo até hoje, sendo o
meu exemplo até hoje. Marco Marocci e Robson Mário, que são como pais para mim e ao meu irmão
Leonardo Araújo que sempre esteve comigo quando eu precisei e que me deu também mais 2 irmãos,
Ramon Pombo e Matheus Pombo.
Gostaria de agradecer a minha mulher, Nilana Rocha, por todo apoio dado. Ela foi um dos fatores
cruciais e com certeza sem ela este livro não seria uma realidade. Muito obrigado por tudo.
Um grande momento para lembrar de todos os meus amigos do Grupo LinguÁgil e #horaExtraSSA
de Salvador-BA. Vocês foram pessoas que me motivaram a ser o profissional que sou atualmente,
que me motivaram a buscar e compartilhar conhecimento. Obrigado a todos vocês. Ao pessoal de
Recife que são pessoas que tenho muito carinho e me apresentaram queijo coalho, macaxeira (ou
aipim?) e muito carinho.
Por último, gostaria de agradecer Nelson Glauber4 e Fagner Brack5 pelo suporte na revisão do
conteúdo deste livro e a todos que me ajudaram direta ou indiretamente na composição deste livro,
como Rafael Gomes6 , Juliano Bersano7 , Sarah Atkinson8 e vários outros que me deram suporte neste
processo e sugeriram melhorias nesta etapa.
Muito obrigado a todos.
Wilson Mendes
4
https://twitter.com/nglauber
5
https://twitter.com/fagnerbrack
6
https://twitter.com/gomex
7
https://twitter.com/julianobersano
8
https://twitter.com/SarahvAko
Nodebots e microcontroladores
O que são nodebots?
NodeBots é um termo utilizado para definir o conceito de controle sobre open hardware, um
hardware eletrônico projetado e oferecido da mesma maneira e com as mesmas licenças que um
software de código livre, sensores e outros componentes eletrônicos utilizando NodeJS. E você pode
utilizar vários elementos: desde sensores, servo motores9 , rodas, detectores de movimento, câmeras,
displays de LED, reprodutores de áudio e muito mais.
Em alguns momentos o conceito de Nodebots está diretamente conectado ao conceito de IoT -
Internet das Coisas. Do inglês Internet of Things é uma revolução tecnológica a fim de conectar
aparelhos eletrônicos do nosso cotidiano, como aparelhos eletrodomésticos e até mesmo máquinas
industriais e aparelhos com acesso à internet e outras inovações técnicas em campos importantes
como o da automação domiciliar a partir de sensores.
Toda a ideia de NodeBots evoluiu de acordo com as capacidades crescentes no NodeJS e o esforço de
alguns desenvolvedores como Nikolai Onken, Jörn Zaefferer, Chris Williams, Julian Gautier e Rick
Waldron que trabalharam para desenvolver os vários módulos que usamos em aplicações NodeBots
hoje em dia. O módulo node-serialport10 , criado por Chris Williams, foi o pontapé inicial pois permite
o acesso a dispositivos utilizando processos de leitura e escrita a portas seriais em baixo nível.
Julian Gautier, em seguida, implementou o Firmata11 , um protocolo usado para acesso a microcon-
troladores, como Arduinos, via código usando JavaScript para a comunicação entre componentes
físicos.
Rick Waldron foi um pouco mais além. Usando a biblioteca Firmata como base, ele criou um
framework para auxiliar na construção de Nodebots e Internet das coisas chamado Johnny-Five.
O framework Johnny-Five torna o controle de vários componentes, desde LEDs até vários outros
tipos de sensores de uma maneira simples e prática. Isto é o que muitos NodeBots agora usam para
atingir alguns feitos impressionantes!
Microcontroladores
Quando falamos de nodebots, estamos indiretamente mencionando microcontroladores, que é um
computador menor e mais simples. Ele possui uma placa programável simples de circuito físico
(citaremos como pinos, entradas, etc) que pode detectar várias entradas e saídas.
9
https://pt.wikipedia.org/wiki/Servomotor
10
https://www.npmjs.com/package/serialport
11
https://www.npmjs.com/package/firmata
Nodebots e microcontroladores 5
Um Arduino é um dos vários tipos de microcontroladores, sendo um dos mais comuns para
experimentos e validações entre software e hardware, mas existem outros tipos que pode ser
alimentado por NodeJS, como por exemplo:
• Raspberry Pi12 ;
• Tessel13 ;
• Espruino14 ;
• BeagleBone15 ;
Neste livro utilizarei o Arduino UNO16 nos exemplos, mas sinta-se livre para utilizar o microcontro-
lador de sua escolha.
NodeJS
NodeJS é um runtime de execução JavaScript construído com base na engine Javascript V8 do
Chrome, possibilitando a utilização do Javascript em outros ambientes além da web e com um
aspecto importante que é a utilização de um modelo não-bloqueante de entrada e saída de dados
orientado a eventos. Possui o objetivo de ajudar programadores na criação de aplicações de alta
escalabilidade como servidores web com conexões simultâneas, scripts assíncronos e até mesmo a
integração com componentes eletrônicos que é o nosso caso.
Foi criado por Ryan Dahl em 2009, e seu desenvolvimento é mantido pela comunidade e pela Node
Foundation, da qual empresas como IBM, Google, Red Hat, Joyent, dentre outras.
Instalando no Windows
Instalar o NodeJS no Windows é bem simples. Uma das maneiras é visitar o website oficial do
projeto17 e baixar o instalador no formato, clicar nas opções de instalação e finalizar a instalação.
Quando finalizar abra o seu prompt de comando acessando pelo prompt de comando do Windows
a partir do comando “Executar > cmd” e, após iniciar o programa, digite o seguinte comando:
1 $ node -v
Ele deve exibir no prompt a versão atual do NodeJS no seu terminal. Com isso finalizamos a
instalação no ambiente Windows.
12
https://www.raspberrypi.org/
13
https://tessel.io/
14
http://www.espruino.com/
15
http://beagleboard.org/bone
16
https://www.arduino.cc/en/Main/ArduinoBoardUno
17
https://nodejs.org/en/download/
Nodebots e microcontroladores 6
Wget:
Pacotes como CURL e WGET podem não estar instalados em seu sistema operacional
por padrão. Caso precise, verifique a melhor forma de instalação para o seu sistema
operacional ou acesse o repositório do NVM no Github para verificar os passos de
instalação ou possíveis soluções de problema.
Logo a seguir, você deve abrir o seu arquivo que guarda a configuração padrão de seu terminal,
que pode estar localizado no ∼/.bash_profile, ∼/.zshrc, ∼/.profile ou ∼/.bashrc, e adicionar
estas linhas no final deste arquivo de configuração para que carregue o NVM no momento em que
você acesse a linha de comando.
1 export NVM_DIR="$HOME/.nvm"
2 [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
Com isso, assim que você recarregar o seu terminal o NVM estará disponível. Agora basta instalar
a versão do NodeJS de sua preferência. Neste livro utilizaremos a versão 5.3.0.
Após estes comandos o NVM fará o download da versão específica do NodeJS, deixando-a acessível
via terminal. Para verificar se o comando foi concluído com sucesso, digite o comando:
18
https://github.com/creationix/nvm
Nodebots e microcontroladores 7
1 $ node -v
O resultado deve ser v5.3.0. Se este foi o retorno do seu comando, está tudo pronto para os nossos
próximos passos. Caso tenha algum problema verifique se o código de carregamento do NVM foi
inserido no arquivo de configuração do seu terminal e inicie outra instância do seu terminal.
Foi criado um arquivo com os comandos contidos neste tópico para a instalação do NVM e o Node
com a versão utilizada neste livro. Caso queira utilizá-lo, por favor faça o download do arquivo
nvm-install.sh19 .
Para continuar será necessário responder a algumas perguntas básicas sobre o projeto, tais como: -
Nome do pacote; - Versão do projeto; - Descrição sobre o projeto; - Nome do arquivo principal do
projeto. Este será produzido no final do seu projeto, depois de todos os tratamentos de minificação,
obfuscação e outros procedimentos de otimização do seu código javascript;
19
https://gist.github.com/willmendesneto/4c951413bacbb8850837a53bcdada30d
20
https://docs.npmjs.com/cli/init
Nodebots e microcontroladores 8
Pode ficar tranquilo que nenhuma delas é obrigatória. Caso não saiba ou não queira responder agora,
basta clicar na tecla “Enter” até o final. Em seguida, ele vai criar um arquivo package.json com estas
informações do seu repositório.
output do comando
Adicionando pacotes
Agora que já temos o nosso package.json21 com todas as configurações básicas do nosso repositório,
vamos instalar o nosso primeiro pacote para integrarmos com o nosso projeto!
O NPM funciona como o gerenciador de pacotes oficial para aplicações NodeJS, sendo o maior
ecossistema de bibliotecas e módulos open source do mundo.
Com ele você pode adicionar pacotes em sua aplicação a partir do comando npm install22 informando
o nome do pacote publicado no site oficial do npm e o formato que queremos salvar o pacote na
aplicação. Temos algumas opções de adição de pacotes que são:
• localmente como uma dependência do seu projeto: o pacote será instalado localmente e aces-
sível na pasta node_modules e as informações do pacote serão salvas na chave dependencies
do seu arquivo JSON. Para usar esta opção adicione a flag --save;
• globalmente: o pacote será instalado com escopo global e acessível em qualquer outro projeto.
Para usar esta opção adicione a flag --global;
Para o nosso projeto inicial vamos instalar o framework Johnny-Five como uma das dependências
de desenvolvimento, rodando o comando:
Você pode perceber que agora temos alguns arquivos novos na pasta do nosso projeto.
Primeiramente, foi criada a pasta node_modules e dentro dela temos o nosso pacote instalado com
sucesso.
Outra novidade foi a adição das informações do nosso pacote no bloco de conteúdo dependencies
no nosso arquivo package.json.
1 {
2 "name": "hello-world",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1"
8 },
9 "author": "",
10 "license": "ISC",
11 "dependencies": {
12 "johnny-five": "^0.10.0"
13 }
14 }
O npm possui vários outros comandos padrão que podemos utilizar em nossa aplicação.
Caso queira saber mais sobre estes comandos, acesse a página sobre estes comandos na
documentação oficial do NPM23 .
23
https://docs.npmjs.com/misc/scripts
Nodebots e microcontroladores 11
1 {
2 "name": "hello-world",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "dev": "echo \"This is our 'dev' NPM task\"",
8 "test": "echo \"Error: no test specified\" && exit 1"
9 },
10 "author": "",
11 "license": "ISC",
12 "dependencies": {
13 "johnny-five": "^0.10.0"
14 }
15 }
Notem que na linha 7, em negrito, adicionamos o nosso novo comando NPM através do campo
“scripts” do JSON. Reparem que já tínhamos o comando “test” que é um comando padrão do npm
e está na mesma área do nosso novo comando, pois esta é a área padrão para adicionarmos os
comandos a serem executados pelo NPM.
Para rodarmos o comando, basta acessarmos o nosso terminal ou prompt de comando e digitarmos
npm run dev. O resultado retornará da seguinte forma:
Nodebots e microcontroladores 12
Arduino
Arduino…ardu-o-que?
Arduino é uma plataforma open-source baseada em um hardware de fácil utilização e integração
com sensores a partir do software. Por tratar-se de uma plataforma totalmente maleável e aberta
qualquer um pode utilizá-lo em projetos dos mais diversos como simples verificações de dados
recebidos por sensores de luz, temperatura, umidade ou até mesmo automação domiciliar.
Dentre as suas vantagens encontramos:
Existe uma página na Wiki do projeto Arduino com soluções para os problemas mais comuns27 , caso
vocês tenham algum tipo de inconveniente com a instalação e primeiro setup do Arduino IDE.
É possível codificar utilizando o seu editor ou IDE preferido e iniciar esta etapa
utilizando o pacote interchange28 . O intuito do conteúdo a seguir é facilitar o setup
do arduino para desenvolvedores que estão tendo o primeiro contato com a plataforma
Arduino.
Feita a instalação do Arduino IDE, vamos agora acessar o programa e verificar o seu funcionamento.
Primeiramente percebemos que o Arduino IDE possui alguns exemplos integrados como um
mediador e facilitador para quem nunca teve contato com a plataforma. Para verificar a lista
completa de exemplos basta acessar a opção File > Examples.
Vale lembrar que os códigos de exemplo são escritos na [linguagem C](https://pt.wikipedia.org/wiki/C_-
(linguagem_de_programa%C3%A7%C3%A3o) e não em Javascript, mas nada impede de rodar o
código exemplo em seu sistema operacional.
27
https://github.com/arduino/Arduino/wiki/Building-Arduino
28
https://github.com/johnny-five-io/nodebots-interchange
Nodebots e microcontroladores 14
Vamos agora conectar a nossa placa Arduino ao nosso sistema operacional. Como já conectei
anteriormente, o Arduino IDE já armazenou a configuração do meu Arduino, que aparece no item
“Board: Arduino Genuino/UNO”, mas na primeira utilização aparecerá na opção “Port”, que possui
a listagem completa das portas seriais de seu sistema operacional.
Nodebots e microcontroladores 15
O nome aparecerá com o prefixo “/dev/cu.” e possuirá o nome do Arduino, facilitando a integração.
Escolha a porta na qual o seu Arduino está conectado e pronto: a conexão foi efetuada com sucesso.
Firmata
Firmata é um protocolo para a comunicação com os microcontroladores de software em um
computador (ou smartphone / tablet, etc). O protocolo pode ser implementado no firmware de
qualquer arquitetura microcontrolador, bem como em qualquer pacote de software de computador.
O nosso próximo passo após a instalação do Arduino IDE é adicionarmos o protocolo Firmata no
nosso Arduino. Vamos abrir o nosso Arduino IDE e acessar a opção Files > Examples > Firmata >
StandardFirmata.
Nodebots e microcontroladores 16
Com o Arduino plugado no nosso computador rodamos o código a seguir e aguardamos a mensagem
da IDE de que tudo ocorreu com sucesso.
Nodebots e microcontroladores 17
Johnny Five
Johnny-Five é um framework open source que permite que você controle um micro-controladores e
componentes utilizando funções muito similares as que seriam utilizadas se você estivesse progra-
mando apenas para a plataforma Arduino em si, porém utilizando JavaScript e implementando o
protocolo Firmata para comunicação com o software no computador host.
Isso permite que você escreva um firmware personalizado sem ter que criar o seu próprio protocolo
e objetos para o ambiente de programação que você está usando. Resumindo, Johnny-Five é um
pacote node que irá permitir programar micro controladores utilizando JavaScript!
Nodebots e microcontroladores 18
Após este comando, o NPM vai criar a pasta node_modules e dentro dela teremos o nosso pacote
johnny-five instalado e acessível no contexto do nosso projeto.
Podemos verificar também que o nosso package.json foi alterado. Nele foram adicionadas as
informações do nome do nosso pacote NodeJS e a versão instalada, como podemos ver no código a
seguir.
1 {
2 "name": "hello-world",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1"
8 },
9 "author": "",
10 "license": "ISC",
11 "dependencies": {
12 "johnny-five": "^0.10.0"
13 }
14 }
1 ...
2 var five = require('johnny-five');
3 ...
Nodebots e microcontroladores 19
Este comando faz a requisição do pacote, tornando-o acessível ao nosso projeto. Agora conheceremos
a nossa primeira classe do Jonny Five: o Board.
A classe Board retorna para a aplicação um objeto que representa a própria placa física na eletrônica.
Todos os objetos dispositivo dependem deste objeto para serem inicializados.
1 ...
2 var board = new five.Board();
3 ...
O objeto board possui um método .on(), que é comumente usado em aplicações Javascript para
criação de event handlers. Este método aceita 2 parâmetros:
• Nome do evento;
• função a ser executada quando o evento for acionado;
Neste exemplo chamaremos este método com a opção ready, que verifica quando o código já está
acessando a placa física utilizada.
1 ...
2 board.on('ready', function() {
3 console.log('Hello World!');
4 });
5 ...
E o conteúdo final do nosso index.js ficou bem enxuto, como podem ver abaixo.
Agora podemos rodar o nosso código via linha de comando digitando o comando:
1 $ node index.js
Nodebots e microcontroladores 20
E o resultado retornado será a mensagem “Hello World”, como vocês podem ver na figura abaixo.
Caso queiram facilitar, podemos utilizar o npm start, um dos comandos NPM padrão que podemos
criar no nosso package.json, tornando-o acessível via linha de comando.
1 {
2 "name": "hello-world",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "start": "node index.js",
8 "dev": "echo \"This is our 'dev' NPM task\"",
9 "test": "echo \"Error: no test specified\" && exit 1"
10 },
11 "author": "",
12 "license": "ISC",
13 "dependencies": {
14 "johnny-five": "^0.10.0"
15 }
16 }
Após adicionarmos o comando, basta digitarmos na linha de comando npm start e o resultado será
a mesma mensagem do comando anterior.
Neste tópico vocês viram a integração entre o nosso código Javascript com o hardware. Nos próximos
capítulos veremos mais exemplos mostrando de uma maneira simples e divertida como integrar
Nodebots ao nosso cotidiano.
Primeiro projeto: Build Checker
O que é um build pipeline
Em algumas apresentações percebi que este termo não é conhecido por muitas pessoas, mesmo as
que são mais familiarizadas com abordagens como integração contínua e entrega contínua.
Build pipeline é um conceito que foi construído em meados de 2005 e é baseado na ideia de
paralelização de tarefas, separando cada etapa em pequenos critérios de aceitação para a aplicação.
Vale lembrar que esses passos podem automáticos ou manuais.
Material necessário
Para este projeto utilizaremos:
• 1 Protoboard: Uma protoboard nada mais é que uma placa com furos e conexões condutoras
para montagem de circuitos elétricos experimentais, sem a necessidade de soldagem. Um
protoboard simples custa entre R$ 5,00 a R$ 10,00 e pode ser encontrado em qualquer loja
de elétrica;
• 2 LEDS (light-emitting diode): 1 vermelha para sinalizar o build quebrado e 1 verde para
sinalizar o que o build foi concluído com sucesso. Uma LED custa menos de R$ 0,50 e pode
ser encontrada em qualquer loja de elétrica;
• Arduino com 2 portas GND (ground);
Portas GND são chamadas de portas “terra”. São condutores elétricos que conectam-se à Terra - ou
seja, ao Terra Elétrico. Uma vez que encontra-se sempre neutro e (teoricamente) presente em todo
circuito elétrico, é sempre tomado como ponto de referência para a medida de potenciais, contendo
zero volts.
Agora basta plugarmos as 2 LEDS, vinculando da seguinte forma:
Controlando a LED
Conhecendo os componentes que utilizaremos, vamos agora ao nosso código inicial que vai controlar
a nossa LED. Primeiramente criaremos a pasta src, onde ficará o código de nossa aplicação.
Vamos criar a pasta do nosso projeto build-checker e navegarmos para a pasta criada.
1 $ mkdir build-checker
2 $ cd build-checker
Iniciaremos a nossa aplicação digitando o comando npm init com a flag -y que significa que todas
as respostas que foram feitas anteriormente serão respondidas e cadastradas com a resposta padrão.
Após isto instalaremos o pacote johnny-five localmente como uma dependência na pasta do nosso
projeto.
Primeiro projeto: Build Checker 24
1 $ npm init -y
2 $ npm install --save johnny-five
Dentro da pasta do nosso projeto criaremos a pasta src e dentro dela o nosso arquivo index.js,
onde ficará o nosso conteúdo.
1 $ mkdir src
2 $ touch src/index.js
1 ...
2 var five = require('johnny-five');
3 var board = new five.Board();
4 ...
Para a primeira atividade com o componente utilizaremos uma nova classe do Johnny Five chamada
LED. Para utilizarmos esta classe precisamos passar o valor do pino que o LED está conectado ao
Arduino.
1 ...
2 var led = new five.Led(12);
3 ...
Agora vamos colocar o nosso código para funcionar no nosso Arduino. Dentro da pasta do nosso
projeto, vamos digitar no nosso prompt de comando/terminal o seguinte comando:
Primeiro projeto: Build Checker 25
1 $ node src/index.js
Após este comando o nosso prompt/linha de comando está mostrando que o comando rodou com
sucesso e o resultado será que as nossas duas LEDs estarão piscando.
Bastante simples, não é mesmo? No próximo tópico vamos pensar um pouco mais sobre a nossa
arquitetura.
Ao cadastrar o projeto ele vai aparecer na parte superior, à direita, um campo com o nome “CCTray”
que, ao clicarmos, direciona para o arquivo XML com as informações do build.
32
https://snap-ci.com
33
http://www.martinfowler.com/articles/continuousIntegration.html
Primeiro projeto: Build Checker 26
1 <Projects>
2 <Project
3 name="brasil-de-fato/news-service (master) :: CONTRACT-TEST"
4 activity="Sleeping"
5 lastBuildLabel="77"
6 lastBuildStatus="Success"
7 lastBuildTime="2016-01-21T18:46:48Z"
8 webUrl="https://snap-ci.com/brasil-de-fato/news-service/branch/master/logs/defau\
9 ltPipeline/77/CONTRACT-TEST"/>
10 </Projects>
Analisando as informações percebemos que a única informação que devemos validar para o nosso
build são os dados do campo lastBuildStatus. Nele é retornado se o build foi finalizado com sucesso,
finalizado com sucesso ou está acontecendo no momento da validação.
O campo lastBuildStatus pode conter:
Vamos agora adicionar a nossa URL que contém as informações do CCTray do nosso projeto e
criar com a requisição destas informações. Para isso vamos adicionar o pacote NodeJS request34 ,
34
https://github.com/request/request
Primeiro projeto: Build Checker 27
um cliente HTTP que foi desenvolvido com o intuito de facilitar a criação de requisições HTTP ou
HTTPS. Para adicionarmos o novo pacotes vamos digitar o seguinte comando.
Agora vamos adicionar o pacote no nosso projeto e criarmos a requisição usando o módulo
RequestJS.
1 ...
2 var request = require('request');
3 var five = require('johnny-five');
4 var board = new five.Board();
5 ...
E vamos adicionar o endereço co CCTray que copiamos do nosso servidor de integração contínua
no nosso código e criaremos a requisição HTTP para leitura das informações.
• error: um objeto com as informações do erro que aconteceu. Caso a requisição não retorne
nenhum erro ele possui o valor padrão null;
• response: objeto com as informações do response da requisição;
• body: String com as informações do body do retorno da requisição;
No nosso código então vamos analisar o retorno da requisição e criar os devidos tratamentos. O
primeiro tratamento será a verificação do erro e, caso tenhamos um erro trataremos o erro.
35
https://github.com/request/request#table-of-contents
Primeiro projeto: Build Checker 28
1 ...
2 request(CI_CCTRACKER_URL, function(error, response, body) {
3 if (error) {
4 console.log('Something is wrong in our CI/CD =(');
5 return;
6 }
7 ...
8 });
Caso o response não retorne nenhum erro, trataremos a mensagem para ligarmos e desligarmos as
LEDs para o feedback visual.
1 ...
2 if(body.indexOf('Failure') !== -1) {
3 console.log('Your CI/CD is broken! Fix it!!!!');
4 ledSuccess.off();
5 ledError.on();
6 } else {
7 console.log('Your CI/CD is ok!');
8 ledSuccess.on();
9 ledError.off();
10 }
11 ...
Com a requisição criada, vamos somente criar um intervalo entre cada requisição, utilizando um
simples setInterval. Vamos utilizar um tempo de 500 milisegundos para validação do código, mas
este valor pode ser alterado para o que for ideal ao seu caso.
1 setInterval(function(){
2 request(CI_CCTRACKER_URL, function(error, response, body) {
3 ..
4 });
5 }, 500);
build, baseado nas informações de todas as pipelines. Caso não haja a palavra “Failure” no response
da requisição, algo de errado aconteceu e o nosso build checker irá acender a luz vermelha, caso
contrário a luz verde continua acesa, sinalizando que está tudo ok.
1 // src/configuration.js
2 module.exports = {
3 LED: {
4 SUCCESS: 12,
5 ERROR: 10
6 },
7 CI_CCTRACKER_URL: 'https://snap-ci.com/willmendesneto/generator-reactor/branch\
8 /master/cctray.xml',
9 INTERVAL: 1000
10 };
Agora vamos alterar o nosso src/index.js para utilizar o nosso arquivo com as configurações
padrão da nossa aplicação
13 ...
14 });
15 }, CONFIG.INTERVAL);
16 });
O nosso código está começando a ficar um pouco mais expressivo, concordam? Mas ainda tem algo
que podemos melhorar? Claro que sim!
Estamos falando sobre o build checker, mas não temos nenhuma abstração para esta operação.
A idéia é que o nosso código final seja somente uma inicialização do nosso app, com todas as
informações relevantes dentro desta abstração.
Vamos então criar o nosso arquivo com as abstrações de informações de LED e da requisição HTTP,
acessando as configurações.
29 } else {
30 console.log('Somethink is wrong with your CI =(. Fix it!!!!');
31 self.ledSuccess.off();
32 self.ledError.on();
33 }
34
35 });
36 }, CONFIG.INTERVAL);
37 };
38
39 module.exports = BuildChecker;
E o nosso arquivo src/index.js irá somente invocar e iniciar o nosso código para que as LEDs
comecem a piscar.
Pirâmide de testes
Falaremos apenas em testes de unidade, se você gostaria de saber mais sobre todas as camadas, leia
o post “TestPyramid”37 de Martin Fowler.
A idéia do teste unitário é validar e certificar que seu código está fazendo o que ele se propõe a fazer,
dando o feedback sobre os erros rapidamente antes de efetuarmos o deploy do nosso projeto para
produção.
Um aspecto que ninguém explica muito bem é sobre os testes em Nodebots, que tem como
objetivo principal neste caso criar as simulações elétricas e com mocks e stubs simulando assim
a comunicação entre componentes.
Vamos agora criar uma pasta para os nossos testes unitários com o nome test.
1 $ mkdir test
Os testes unitários utilizarão o framework de teste MochaJS38 , SinonJS39 para spies, stubs e
mocks e ShouldJS40 para as assertions. Vamos então instalar estes pacotes como dependência de
desenvolvimento do projeto.
37
http://martinfowler.com/bliki/TestPyramid.html
38
https://mochajs.org
39
http://sinonjs.org
40
https://shouldjs.github.io
Primeiro projeto: Build Checker 34
Um pacote NodeJS fundamental nesta etapa é o mock-Firmata41 , criado por Rick Waldron para fazer
o setup dos testes em aplicações Johnny-Five mais fácil. A integração é muito simples, você só precisa
carregar e criar seu componente fake da placa no teste, como podemos ver no nosso arquivo de setup
dos testes test/spec-helper.js.
1 require('should');
2 var mockFirmata = require('mock-firmata');
3 var five = require('johnny-five');
4
5 var board = new five.Board({
6 io: new mockFirmata.Firmata(),
7 debug: false,
8 repl: false
9 });
Vamos então adicionar um teste simples para checar a integração dos nossos testes. Primeiramente
criaremos um arquivo com algumas configurações do MochaJS dentro da pasta test. Este será o
conteúdo inicial do nosso mocha.opts.
1 --reporter spec
2 --recursive
3 --require test/spec-helper.js
4 --slow 1000
5 --timeout 5000
41
https://github.com/rwaldron/mock-firmata
Primeiro projeto: Build Checker 35
Os nossos testes utilizam os métodos de escopo describe e it. O describe é utilizado agrupar
cenários, no nosso caso o Test validation. Já o it é a identificação de um dos pontos de teste.
Percebam também que temos o método should.be.equal que vai comparar se o primeiro valor é
igual ao segundo.
1 $ ./node_modules/bin/mocha
Veremos então estas informações no nosso prompt/terminal e o nosso setup inicial foi um sucesso!
Agora sim, vamos criar os cenários para os nossos testes. Vamos então definir os cenários que
devemos cobrir nos nossos testes:
• Quando paramos o nosso polling e não faremos mais requisições de dados para o nosso
servidor;
Uma forma de validarmos quando o build checker deve piscar o LED é criarmos um stub para a
solicitação utilizando o node-request para validar a resposta por tipos esperados (success e error)
e usaremos alguns spies para os LEDs.
Para esta simulação vamos criar algumas fixtures com o modelo das respostas do servidor para
sucesso e erro. Vamos então criar a nossa pasta com os dados dentro de nossa pasta que contém os
nossos testes.
1 $ mkdir test/fixtures
2 $ touch test/fixtures/success.xml test/fixtures/error.xml
Vamos então criar o cenário para validar o nosso código. Algumas coisas devemos ter em mente
sobre o nosso framework de teste unitário é que o seu método beforeEach, que acontece antes de
cada método it. Utilizaremos como documentação de cada etapa que deve ocorrer para reproduzir
o cenário específico.
Vamos então explicar mais sobre o conteúdo deste arquivo e o porquê de cada teste. Criamos os
testes da instância do nosso BuildChecker e seus atributos iniciais.
Primeiro projeto: Build Checker 37
Agora vamos validar quando paramos o nosso polling. Vamos usar agora o método spy do sinon
para verificar se o código utilizou o método clearInterval para finalizar com as requisições. Para isso
verificaremos se o global.clearInterval foi utilizado uma vez, acessando o boolean calledOnce,
que é um contador interno adicionado pelo método sinon.spy para os testes.
1 ...
2 describe('#stopPolling', function(){
3 beforeEach(function(){
4 sinon.spy(global, 'clearInterval');
5 buildChecker.stopPolling();
6 });
7
8 it('should remove interval', function(){
9 global.clearInterval.calledOnce.should.be.true;
10 });
11 });
12 ...
E agora os cenários do servidor respondendo com sucesso e falha. Para isto vamos atribuir os nossos
dados da pasta fixtures em variáveis.
Primeiro projeto: Build Checker 38
1 ...
2 var fs = require('fs');
3 var successResponseCI = fs.readFileSync(__dirname + '/fixtures/success.xml', 'ut\
4 f8');
5 var errorResponseCI = fs.readFileSync(__dirname + '/fixtures/error.xml', 'utf8');
6 ...
Perceba que em cada um dos casos de sucesso e falha estamos utilizando o método sinon.useFakeTimers,
que é uma maneira de simular eventos vinculados a objetos timer no Javascript.
Quando chamamos o método clock.tick com a informação contida no arquivo de configuração,
simulamos alterações de horário e tempo no momento do teste, o que nos ajuda a forçar a chamada
do evento de polling, que utiliza o setInterval.
1 ...
2 clock = sinon.useFakeTimers();
3 clock.tick(CONFIG.INTERVAL);
4 ...
Utilizamos agora o método stub do sinon para o pacote node-request. Com isso podemos alterar
o retorno quando o método request.get for chamado. Neste caso podemos simular o response de
cada requisição, com base nas informações das nossas fixtures.
1 ...
2 sinon.stub(request, 'get').yields(null, null, successResponseCI);
3 ...
Um ponto importante nos nossos testes é lembrar de restaurar todas as informações de stub e
do fakeTimers. Utilizaremos o afterEach, método que é chamado sempre após cada método it,
e adicionaremos os nossos objetos chamando o método restore adicionado pelo sinon.
1 ...
2 afterEach(function(){
3 request.get.restore();
4 clock.restore();
5 });
6 ...
Com base nos nossos cenários de teste, este é o conteúdo do teste do nosso arquivo build checker:
Primeiro projeto: Build Checker 39
1 // test/build-checker.js
2
3 var BuildChecker = require('../src/build-checker');
4 var CONFIG = require('../src/configuration');
5 var five = require('johnny-five');
6 var request = require('request');
7 var sinon = require('sinon');
8 var fs = require('fs');
9 var successResponseCI = fs.readFileSync(__dirname + '/fixtures/success.xml', 'ut\
10 f8');
11 var errorResponseCI = fs.readFileSync(__dirname + '/fixtures/error.xml', 'utf8');
12 var clock = null;
13
14 describe('BuildChecker', function() {
15
16 beforeEach(function(){
17 buildChecker = new BuildChecker();
18 });
19
20 it('should have the led success port configured', function(){
21 (buildChecker.ledSuccess instanceof five.Led).should.be.equal(true);
22 });
23
24 it('should have the led error port configured', function(){
25 (buildChecker.ledError instanceof five.Led).should.be.equal(true);
26 });
27
28 describe('#stopPolling', function(){
29 beforeEach(function(){
30 sinon.spy(global, 'clearInterval');
31 buildChecker.stopPolling();
32 });
33
34 it('should remove interval', function(){
35 global.clearInterval.calledOnce.should.be.true;
36 });
37 });
38
39 describe('#startPolling', function(){
40 beforeEach(function(){
41 sinon.spy(global, 'setInterval');
42 buildChecker.startPolling();
Primeiro projeto: Build Checker 40
43 });
44
45 afterEach(function(){
46 global.setInterval.restore();
47 });
48
49 it('should creates polling', function(){
50 global.setInterval.calledOnce.should.be.true;
51 });
52
53 describe('When the CI server send success response', function(){
54 beforeEach(function() {
55 clock = sinon.useFakeTimers();
56 sinon.stub(request, 'get').yields(null, null, successResponseCI);
57 sinon.spy(buildChecker.ledSuccess, 'on');
58 sinon.spy(buildChecker.ledError, 'off');
59 buildChecker.startPolling();
60 clock.tick(CONFIG.INTERVAL);
61 });
62
63 afterEach(function(){
64 request.get.restore();
65 clock.restore();
66 });
67
68 it('should turn on the success led', function(){
69 buildChecker.ledSuccess.on.calledOnce.should.be.true;
70 });
71
72 it('should turn off the error led', function(){
73 buildChecker.ledError.off.calledOnce.should.be.true;
74 });
75
76 });
77
78 describe('When the CI server send error response', function(){
79 beforeEach(function() {
80 clock = sinon.useFakeTimers();
81 sinon.stub(request, 'get').yields(null, null, errorResponseCI);
82 sinon.spy(buildChecker.ledError, 'on');
83 sinon.spy(buildChecker.ledSuccess, 'off');
84 buildChecker.startPolling();
Primeiro projeto: Build Checker 41
85 clock.tick(CONFIG.INTERVAL);
86 });
87
88 afterEach(function(){
89 request.get.restore();
90 clock.restore();
91 });
92
93 it('should turn off the success led', function(){
94 buildChecker.ledSuccess.off.calledOnce.should.be.true;
95 });
96
97 it('should turn on the error led', function(){
98 buildChecker.ledError.on.calledOnce.should.be.true;
99 });
100
101 });
102
103 });
104
105 });
Este é apenas um dos vários formatos de testes unitários para a sua aplicação. Com isso terminamos
o nosso primeiro projeto com testes unitários baseado nos nossos possíveis cenários, mas caso queira
fazer download ou fork do código final, acesse o repositório do projeto build checker no Github42 .
Vamos para o nosso próximo projeto com Nodebot e Johnny-five?
42
https://github.com/willmendesneto/build-checker
Segundo projeto: Alarme de incêndio
O nosso segundo projeto de exemplo será o de um alarme de incêndio inteligente. O nosso alarme
de incêndio verificará pela temperatura e, em caso de incêndio, acionará o alarme sonoro e enviará
um SMS para o celular cadastrado.
Um exemplo simples, mas que mostra alguns pontos de integração interessantes, como integração
com API’s, leitura de dados de um sensor de temperatura e integração com o sensor sonoro Piezo.
Material necessário
Para este projeto utilizaremos:
• 1 Protoboard: Uma protoboard nada mais é que uma placa com furos e conexões condutoras
para montagem de circuitos elétricos experimentais, sem a necessidade de soldagem;
• 1 sensor de alarme Piezo: Ele será utilizado para o feedback sonoro ao usuário final, no nosso
caso ao(s) inquilino(s) do imóvel. Este sensor é bem simples e custa menos de R$ 2,00 podendo
ser encontrado em qualquer loja de elétrica;
• 1 sensor de temperatura: O Johnny-Five trabalha os mais diversos sensores de temperatura.
Neste caso usaremos o sensor de temperatura LM35. Este sensor é bem simples e custa menos
de R$ 1,50 podendo ser encontrado em qualquer loja de elétrica;
Segundo projeto: Alarme de incêndio 43
• Para obter a lista completa dos sensores suportados acesse a página Wiki do Johnny para
sensores de temperatura43 e verifique a lista dos códigos de referência dos sensores.
Alguns sensores necessitam de uma porta de voltagem específica para o seu correto funcionamento
(alguns sensores chamam de VND). No nosso caso usaremos uma porta de 5 volts para o sensor de
temperatura.
Outros sensores podem precisar de uma porta analógica. Portas analógicas são utilizadas para
que o sensor envie dados de voltagem para o Arduino e assim possamos ler e interpretar as suas
informações.
Para este projeto vamos montar os sensores no Arduino da seguinte maneira:
• Sensor de alarme piezo: encaixe o fio preto do piezo na porta GND e o fio vermelho na porta
de número 3 do nosso arduino;
• Sensor de temperatura LM35: encaixe o pino de aterramento na porta GND, o pino de voltagem
na porta de 5 volts e o pino de saída de dados na porta analógica “A0”;
• controller: Nome do sensor utilizado. Você pode consultar a lista completa dos sensores
suportados pelo Johnny Five na documentação da classe Thermometer44 ;
• pin: A informação do pino utilizado para a conexão analógica no Arduino. Ele é utilizado em
sensores analógicos para leitura da informação de temperatura;
• toCelsius: Um método opcional que podemos reescrever para lidar com o dado analógico e
transformá-lo no formato de temperatura de sua preferência. No nosso caso utilizaremos o
formato Celsius;
Baseado nestas informações, o arquivo principal será do nosso alarme de incêndio será:
Vamos então validar a funcionalidade do nosso código com a plataforma Arduino. Dentro da pasta
do nosso projeto, vamos digitar no nosso prompt de comando/terminal o seguinte comando:
1 $ node src/index.js
44
https://github.com/rwaldron/johnny-five/wiki/thermometer
Segundo projeto: Alarme de incêndio 46
O código é bastante simples, como podem perceber. No próximo tópico vamos pensar um pouco
mais sobre a nossa arquitetura e como evoluir este código para algo mais fácil de manter.
1 // src/configuration.js
2 module.exports = {
3 FIRE_ALARM: {
4 // https://github.com/rwaldron/johnny-five/wiki/thermometer
5 CONTROLLER: "LM35",
6 PIN: 'A0'
7 },
8 INTERVAL: 1000
9 };
Este é o conteúdo do nosso arquivo src/fire-alarm.js. Percebam que agora estamos invocando
o código de configuração externo e adicionando os valores na variável CONFIG. Esta etapa é
interessante, pois desvinculamos as configurações básicas do nosso projeto da classe, que agora
possui a responsabilidade de lidar com os sensores do projeto fire alarm.
Segundo projeto: Alarme de incêndio 47
1 // src/fire-alarm.js
2 var CONFIG = require('./configuration');
3 var five = require('johnny-five');
4 var intervalId = null;
5
6 function FireAlarm() {
7 this.temperatureSensor = new five.Thermometer({
8 controller: CONFIG.FIRE_ALARM.CONTROLLER,
9 pin: CONFIG.FIRE_ALARM.PIN
10 });
11 };
12
13 FireAlarm.prototype.stopPolling = function() {
14 clearInterval(intervalId);
15 };
16
17 FireAlarm.prototype.startPolling = function() {
18 self = this;
19 intervalId = setInterval(function() {
20 console.log('celsius: %d', self.temperatureSensor.celsius);
21 }, CONFIG.INTERVAL);
22 };
23
24 module.exports = FireAlarm;
E o nosso arquivo src/index.js principal vai ter um conteúdo mais simples, tendo a responsabili-
dade de iniciar o projeto e o polling da instância da classe FireAlarm.
1 // src/index.js
2 var FireAlarm = require('./fire-alarm');
3 var five = require('johnny-five');
4 var board = new five.Board();
5
6 board.on('ready', function() {
7 fireAlarm = new FireAlarm();
8 fireAlarm.startPolling();
9 });
Quando executamos o nosso código a partir do comando, veremos o mesmo resultado na nossa linha
de comando/prompt de comando.
Segundo projeto: Alarme de incêndio 48
1 $ npm start
Com essas alterações temos um código de fácil manutenção e muito mais legibilidade para ser
utilizado na nossa aplicação. Claro que esta é uma das várias abordagens que podem ser utilizadas
no seu projeto, mas o foco deste tópico é passar a idéia de sempre pensar em como melhorar o nosso
projeto.
1 ...
2 this.piezo = new five.Piezo(3);
3 ...
Esta classe aceita o número do pino que está vinculado ao sensor e ao ativar temos o método play,
que aceita um objeto com as informações:
Você pode perceber um exemplo do método play sendo utilizado no código abaixo.
1 self.piezo.play({
2 song: [
3 ['G5', 1/4]
4 ],
5 tempo: 200
6 });
No nosso projeto vamos fazer a integração em dividida em 2 partes. Primeiramente vamos adicionar
a instância do piezo no construtor da nossa classe, para que o piezo fique acessível nos outros
métodos.
Segundo projeto: Alarme de incêndio 49
1 ...
2 function FireAlarm() {
3 this.piezo = new five.Piezo(3);
4 ...
5 }
6 ...
Com a nossa instância adicionada e acessível, vamos utilizá-lo no nosso método startPolling. Va-
mos adicionar mais uma validação, acessando o boolean piezo.isPlaying que contém a informação
de inicialização do piezo no nosso projeto e, caso a temperatura esteja acima do limite e o piezo esteja
acessível, acionaremos o nosso alarme sonoro. Com isto o método ficará como o código a seguir.
1 ...
2 FireAlarm.prototype.startPolling = function() {
3 self = this;
4 intervalId = setInterval(function() {
5 if (self.temperatureSensor.celsius >= CONFIG.FIRE_ALARM.LIMIT && !self.piezo\
6 .isPlaying) {
7 self.piezo.play({
8 song: [
9 ['G5', 1/4],
10 [null, 7/4]
11 ],
12 tempo: 200
13 });
14 console.log('Up to the limit:', self.temperatureSensor.celsius);
15 } else {
16 console.log('That\'s ok:', self.temperatureSensor.celsius);
17 }
18 }, CONFIG.INTERVAL);
19 };
20 ...
Com isto temos o primeiro feedback para os usuários da nossa aplicação. A próxima etapa será
adicionar a funcionalidade de envio de SMS utilizando a API do Twilio.
Segundo projeto: Alarme de incêndio 51
Ele possui alguns números pagos, caso queira utilizar em algum produto realmente. No nosso caso
utilizaremos o número gerado pelo próprio serviço e criaremos uma conta trial na plataforma.
45
https://twilio.github.io/twilio-node
Segundo projeto: Alarme de incêndio 52
Agora, com o Twilio configurado, vamos então começar a integração com o nosso alarme de incên-
dio. Primeiramente vamos adicionar as informações do telefone, chave SSID da sua conta e token
de autenticação do Twilio. Vamos adicionar estas informações no nosso src/configuration.js.
1 module.exports = {
2 LIMIT: 30,
3 PIN: 'A0',
4 PHONE_NUMBER: ''
5 },
6 TWILIO: {
7 PHONE_NUMBER: '',
8 ACCOUNT_SSID: '',
9 AUTH_TOKEN: ''
10 },
11 INTERVAL: 1000
12 };
E vamos continuar com a integração do Twilio no nosso código, acessando e lendo as informações
adicionadas no arquivo src/configuration.js com o pacote do Twilio node.
1 // fire-alarm.js
2
3 var CONFIG = require('./configuration');
4 var request = require('request');
5 var five = require('johnny-five');
6 var twilio = require('twilio');
7 var intervalId = null;
8
9 var client = new twilio.RestClient(CONFIG.TWILIO.ACCOUNT_SSID, CONFIG.TWILIO.AUT\
10 H_TOKEN);
11
Segundo projeto: Alarme de incêndio 53
12 function FireAlarm() {
13 this.piezo = new five.Piezo(3);
14 this.temperatureSensor = new five.Thermometer({
15 pin: CONFIG.FIRE_ALARM.PIN
16 });
17 };
18
19 FireAlarm.prototype.stopPolling = function() {
20 clearInterval(intervalId);
21 };
22
23 FireAlarm.prototype.startPolling = function() {
24 self = this;
25 intervalId = setInterval(function() {
26 if (self.temperatureSensor.celsius >= CONFIG.FIRE_ALARM.LIMIT && !self.piezo\
27 .isPlaying) {
28
29 self.piezo.play({
30 song: [
31 ['G5', 1/4],
32 [null, 7/4]
33 ],
34 tempo: 200
35 });
36
37 client.messages.create({
38 body: 'Something is wrong with your fire alarm. Please, call the local f\
39 ire brigade.',
40 to: CONFIG.FIRE_ALARM.PHONE_NUMBER,
41 from: CONFIG.TWILIO.PHONE_NUMBER
42 });
43
44 console.log('Up to the limit:', self.temperatureSensor.celsius);
45 } else {
46 console.log('That\'s ok:', self.temperatureSensor.celsius);
47 }
48 }, CONFIG.INTERVAL);
49 };
50
51 module.exports = FireAlarm;
Vamos agora executar o nosso código digitando o comando npm start e esta será a informação
impressa no nosso prompt/linha de comando.
Segundo projeto: Alarme de incêndio 54
Ao executarmos o nosso código e a temperatura exceder o limite configurado, além do sensor Piezo
que acionará o alarme o nosso cliente do Twilio será acionado e nos enviará um SMS utilizando as
configurações previamente adicionadas. Então você receberá a seguinte mensagem no seu celular.
Com isto vimos a integração completa do nosso Fire Alarm. Claro que este é o primeiro passo, você
pode evoluir o código e adicionar novas funcionalidades. Como já sabemos: o céu é o limite!
Mas e quanto aos testes unitários? Sabemos que está funcionando, mas temos que ter certeza de que
o código tem um nível aceitável de qualidade até mesmo para evoluirmos o nosso projeto e adicionar
novas funcionalidades. Vamos agora criar os nossos testes unitários.
1 $ mkdir test
2 $ npm install --save-dev mocha sinon should
46
https://mochajs.org
47
http://sinonjs.org
48
https://shouldjs.github.io
49
https://github.com/rwaldron/mock-firmata
Segundo projeto: Alarme de incêndio 55
1 //test/spec-helper.js
2 require('should');
3 var mockFirmata = require('mock-firmata');
4 var five = require('johnny-five');
5
6 var board = new five.Board({
7 io: new mockFirmata.Firmata(),
8 debug: false,
9 repl: false
10 });
1 --reporter spec
2 --recursive
3 --require test/spec-helper.js
4 --slow 1000
5 --timeout 5000
Uma forma de validarmos quando o fire alarm deve acionar o alarme sonoro é criarmos um stub
para trigger e usaremos alguns spies para a API do Twilio.
Como primeiro passo criaremos os testes de nosso arquivo de configuração, que dividiremos entre
as informações do sensor de temperatura e da API do Twilio. Faremos a requisição do nosso
src/configuration.js e verificaremos a informação do pino que vai ser vinculado ao sensor, o valor
do intervalo a ser utilizado para checar as informações do sensor e o limite aceitável da temperatura
do ambiente no qual o FireAlarm estará funcionando e o telefone configurado para receber o SMS.
Agora avaliamos as informações que serão passadas para o Twilio, que no nosso caso serão a chave
SSID, token de autenticação e o número telefônico fornecido pelo Twilio.
1 ...
2 describe('SMS information', function() {
3
4 it('should have account ssid configured', function(){
5 CONFIG.TWILIO.should.have.property('ACCOUNT_SSID').which.is.a.String()
6 });
7
8 it('should have auth token configured', function(){
9 CONFIG.TWILIO.should.have.property('AUTH_TOKEN').which.is.a.String()
10 });
11
Segundo projeto: Alarme de incêndio 57
Vamos então criar o cenário para validar o código do nosso FireAlarm. Uma das coisas que devemos
ter em mente sobre o nosso framework de teste unitário é que o seu método beforeEach, que acontece
antes de cada método it vai ser utilizado como documentação para reprodução de cada cenário
específico.
Vamos então explicar mais sobre o conteúdo deste arquivo e o porquê de cada teste. Criamos os
testes da instância do nosso FireAlarm e seus atributos iniciais.
30 afterEach(function() {
31 this.sandbox.restore();
32 });
33
34 it('should have the termometer sensor configured', function(){
35 (fireAlarm.temperatureSensor instanceof five.Thermometer).should.be.equal(tr\
36 ue);
37 });
38
39 });
Vamos validar quando paramos o nosso polling. Vamos usar agora o método spy do sinon para
verificar se o código utilizou o método clearInterval para finalizar com as requisições. Para isso
verificaremos se o global.clearInterval foi utilizado uma vez, acessando o boolean calledOnce,
que é um contador interno adicionado pelo método sinon.spy para os testes.
1 ...
2 describe('#stopPolling', function(){
3 beforeEach(function(){
4 this.sandbox.spy(global, 'clearInterval');
5 fireAlarm.stopPolling();
6 });
7
8 it('should remove interval', function(){
9 global.clearInterval.calledOnce.should.be.true;
10 });
11 });
12 ...
E agora os cenários que acontecem quando o sensor é iniciado. Para isto vamos atribuir alguns spies
para as funções setInterval e para o sensor do piezo. A nossa primeira validação será a certificação
de que o intervalo está sendo iniciado quando invocamos o método fireAlarm.startPolling().
Segundo projeto: Alarme de incêndio 60
1 ...
2 describe('#startPolling', function(){
3 beforeEach(function(){
4 this.piezoPlaySpy = this.sandbox.spy();
5
6 var piezoStub = {
7 isPlaying: false,
8 play: this.piezoPlaySpy
9 };
10 this.sandbox.stub(fireAlarm, 'piezo', piezoStub);
11
12 this.sandbox.spy(global, 'setInterval');
13 fireAlarm.startPolling();
14 });
15
16 afterEach(function(){
17 global.setInterval.restore();
18 });
19
20 it('should creates polling', function(){
21 global.setInterval.calledOnce.should.be.true;
22 });
23 });
24 ...
Para a validação do caso da temperatura acima do limite utilizaremos o método clock.tick com
a informação contida no arquivo de configuração, simulando as alterações de horário e tempo
no momento do teste, o que nos ajuda a forçar a chamada do evento de polling, que utiliza o
setInterval.
Neste cenário utilizamos o stub para simular o retorno do sensor com o valor acima do aceitável e
nos certificamos de que o sensor Piezo e a Api do Twilio foram acionados.
1 ...
2 describe('When the temperature is up to the limit', function(){
3
4 beforeEach(function() {
5 clock = this.sandbox.useFakeTimers();
6
7 this.sandbox.stub(fireAlarm, 'temperatureSensor', {
8 celsius: CONFIG.FIRE_ALARM.LIMIT + 1
9 });
10 fireAlarm.startPolling();
Segundo projeto: Alarme de incêndio 61
11 clock.tick(CONFIG.INTERVAL);
12 });
13
14 afterEach(function(){
15 clock.restore();
16 });
17
18 it('should trigger piezo sensor alarm', function(){
19 this.piezoPlaySpy.calledOnce.should.be.true;
20 });
21
22 it('should send the SMS to user', function() {
23 this.createMessagesSpy.calledOnce.should.be.true;
24 });
25
26 });
27 ...
1 ...
2 describe('When the temperature is NOT up to the limit', function(){
3
4
5 beforeEach(function() {
6 clock = this.sandbox.useFakeTimers();
7
8
9 this.sandbox.stub(fireAlarm, 'temperatureSensor', {
10 celsius: CONFIG.FIRE_ALARM.LIMIT - 1
11 });
12
13
14 fireAlarm.startPolling();
15 clock.tick(CONFIG.INTERVAL);
16 });
17
18
19 afterEach(function(){
20 clock.restore();
Segundo projeto: Alarme de incêndio 62
21 });
22
23
24 it('should NOT trigger piezo sensor alarm', function(){
25 this.piezoPlaySpy.calledOnce.should.be.false;
26 });
27
28
29 it('should NOT send the SMS to user', function() {
30 this.createMessagesSpy.calledOnce.should.be.false;
31 });
32
33
34 });
35 ...
Com base nos nossos cenários de teste, este é o conteúdo do teste do nosso arquivo fire alarm:
25 twilio: twilioMock
26 });
27 fireAlarm = new FireAlarm();
28 });
29
30 afterEach(function() {
31 this.sandbox.restore();
32 });
33
34 it('should have the termometer sensor configured', function(){
35 (fireAlarm.temperatureSensor instanceof five.Thermometer).should.be.equal(tr\
36 ue);
37 });
38
39 describe('#stopPolling', function(){
40 beforeEach(function(){
41 this.sandbox.spy(global, 'clearInterval');
42 fireAlarm.stopPolling();
43 });
44
45 it('should remove interval', function(){
46 global.clearInterval.calledOnce.should.be.true;
47 });
48 });
49
50 describe('#startPolling', function(){
51 beforeEach(function(){
52 this.piezoPlaySpy = this.sandbox.spy();
53
54 var piezoStub = {
55 isPlaying: false,
56 play: this.piezoPlaySpy
57 };
58 this.sandbox.stub(fireAlarm, 'piezo', piezoStub);
59
60 this.sandbox.spy(global, 'setInterval');
61 fireAlarm.startPolling();
62 });
63
64 afterEach(function(){
65 global.setInterval.restore();
66 });
Segundo projeto: Alarme de incêndio 64
67
68 it('should creates polling', function(){
69 global.setInterval.calledOnce.should.be.true;
70 });
71
72 describe('When the temperature is up to the limit', function(){
73
74 beforeEach(function() {
75 clock = this.sandbox.useFakeTimers();
76
77 this.sandbox.stub(fireAlarm, 'temperatureSensor', {
78 celsius: CONFIG.FIRE_ALARM.LIMIT + 1
79 });
80 fireAlarm.startPolling();
81 clock.tick(CONFIG.INTERVAL);
82 });
83
84 afterEach(function(){
85 clock.restore();
86 });
87
88 it('should trigger piezo sensor alarm', function(){
89 this.piezoPlaySpy.calledOnce.should.be.true;
90 });
91
92 it('should send the SMS to user', function() {
93 this.createMessagesSpy.calledOnce.should.be.true;
94 });
95
96 });
97
98 describe('When the temperature is NOT up to the limit', function(){
99
100 beforeEach(function() {
101 clock = this.sandbox.useFakeTimers();
102
103 this.sandbox.stub(fireAlarm, 'temperatureSensor', {
104 celsius: CONFIG.FIRE_ALARM.LIMIT - 1
105 });
106
107 fireAlarm.startPolling();
108 clock.tick(CONFIG.INTERVAL);
Segundo projeto: Alarme de incêndio 65
109 });
110
111 afterEach(function(){
112 clock.restore();
113 });
114
115 it('should NOT trigger piezo sensor alarm', function(){
116 this.piezoPlaySpy.calledOnce.should.be.false;
117 });
118
119 it('should NOT send the SMS to user', function() {
120 this.createMessagesSpy.calledOnce.should.be.false;
121 });
122 });
123 });
124 });
Com isso terminamos o nosso primeiro projeto com testes unitários, cobrindo todos os nossos
possíveis cenários, mas caso queira fazer download ou fork do código final, acesse o repositório do
projeto fire alarm no Github50 . No próximo capítulo veremos outros serviços que facilitam a nossa
vida ao enviarmos o código para produção, tais como servidores de integração contínua, cobertura
de código e de complexidade de maneira automatizada.
50
https://github.com/willmendesneto/fire-alarm
Dando suporte ao seu código em
vários sistemas operacionais
Nesta etapa do livro iremos então validar e verificar a cobertura de testes no nosso projeto em
diferentes sistemas operacionais, além de habilitarmos diferentes serviços web para melhorias de
workflow, como ferramentas de integração contínua e cobertura de código.
Esta etapa é muito importante, pois estas ferramentas nos auxiliam no processo de segurança do
nosso código, checando diferentes critérios de aceitação da nossa aplicação de maneira automatizada.
Após esta etapa você será redirecionado para uma nova página com todos os seus repositórios. Para
adicionarmos um novo basta clicar no ícone “+” ao lado do texto “My Repositories”.
Após esta etapa você será redirecionado para uma nova página com todos os seus repositórios. Para
adicionarmos um novo basta clicar no ícone “+” ao lado do texto “My Repositories”.
Esta próxima etapa é bem simples já que a página possui um tutorial mostrando cada um dos passos
para habilitar a integração do Travis-CI com o seu repositório no Github, como podemos observar
Dando suporte ao seu código em vários sistemas operacionais 68
na imagem abaixo.
Na mesma página, será listado todos os seus repositórios para que você escolha e habilite a integração
do Travis-CI ao seu projeto. Para habilitar basta clicar no botão cinza com um “X” e quando ele mudar
a cor para verde quer dizer que esta tudo correu como esperado e o seu repositório está sincronizado
com o Travis-CI.
O Travis-CI é totalmente configurável e você pode adicionar informações das mais diversas, sendo
elas desde comandos a serem invocados antes, durante ou depois do build, podendo até mesmo
configurar os tipos de sistemas operacionais que as tarefas devem acontecer.
Estas configurações ficarão no arquivo .travis.yml que ficará na pasta raíz do nosso projeto. Vamos
explicar um pouco mais sobre como configurar estas tarefas no Travis-CI.
Primeiramente, no arquivo .travis.yml, vamos adicionar o campo "os", com as devidas informa-
ções dos sistemas operacionais utilizados para os nossos testes.
Dando suporte ao seu código em vários sistemas operacionais 69
1 ...
2 os:
3 - linux
4 - osx
5 ...
Adicionaremos também o campo "node_js", aonde ficarão as nossas informações sobre as versões
de NodeJS que as tasks deverão ser utilizados nas nossas tasks. No nosso caso adicionaremos somente
uma versão, mas poderíamos adicionar várias outras com base nas nossas necessidades de suporte,
por exemplo.
1 ...
2 node_js:
3 - '5.3.0'
4 ...
O nosso servidor de integração contínua nada mais é do que um container com um sistema
operacional completo. Sendo assim podemos também configurar variáveis de ambiente nele. Neste
caso adicionaremos a variável NO_SERIALPORT_INSTALL, especificando que não devemos instalar o
pacote “serialport” neste caso, pois trata-se de um teste que utiliza um mock de um board físico.
OBS: A idéia deste livro é de focar nos conceitos relacionados diretamente com Nodebots e inte-
grações com o repositório javascript criado, por isso não explicarei sobre o conceito de containers.
Caso queira saber mais sobre este conceito utilizado pelo Travis-CI, acesse a página oficial do projeto
Docker53 .
1 ...
2 env:
3 - NO_SERIALPORT_INSTALL=1
4 ...
Podemos também definir o conjunto de tarefas que serão utilizados antes e depois do nosso script do
travis. Neste caso utilizaremos before para os comandos que devem ocorrer antes do nosso script
principal e after para os comandos que devem ocorrer depois dos comandos travis, como vocês
podem visualizar no trecho de código a seguir:
53
https://www.docker.com
Dando suporte ao seu código em vários sistemas operacionais 70
1 ...
2 before_script:
3 - 'npm install'
4
5
6 after_script:
7 - 'make test'
8 ...
Neste caso estamos instalando as nossas dependências e rodando os nossos testes. Tudo isto de
uma maneira bem simples e bem definida. O conteúdo do nosso arquivo .travis.yml com todas
as alterações será o seguinte:
1 language: node_js
2 os:
3 - linux
4 - osx
5 node_js:
6 - '5.3.0'
7 before_script:
8 - 'npm install'
9
10
11 after_script:
12 - 'make test'
13 env:
14 - NO_SERIALPORT_INSTALL=1
Podemos perceber que o build do Travis-CI agora é um pouco diferente, pois estamos rodando o
mesmo setup nos sistemas operacionais Linux e OSX, identificados pelos ícones de cada sistema
operacional.
Com a integração testada, vamos então colocar o badge do travis-ci no nosso arquivo README.md do
repositório. Com isto você verá uma imagem com o status do build.
Dando suporte ao seu código em vários sistemas operacionais 71
1 [![Build Status](https://travis-ci.org/willmendesneto/build-checker.png?branch=m\
2 aster)](https://travis-ci.org/willmendesneto/build-checker)
Com isto terminamos a nossa integração com o servidor de integração contínua Travis-CI e
temos toda a nossa suite de testes rodando nos sistemas Linux e OSX. Nesta próxima etapa
vamos configurar as mesmas tarefas, mas para serem verificadas no sistema operacional Windows,
utilizando outro servidor de integração contínua chamado Appveyor.
Site do Appveyor
54
https://www.appveyor.com/
55
https://en.wikipedia.org/wiki/Cross-platform
Dando suporte ao seu código em vários sistemas operacionais 72
Na página de login temos algumas opções listadas com suporte a alguns dos principais repositórios
de código na internet. Nesta opção vamos utilizar o Github, para facilitar os próximos passos, mas
vale lembrar que você pode utilizar quaisquer das opções suportadas para login.
Com o seu usuário criado e seu acesso funcionando, a página principal após o login é uma página
listando todos os seus repositórios baseado em uma categoria localizada no lado esquerdo do site. No
nosso caso, vamos escolher o projeto build-checker e clicaremos no botão “Add” para adicionarmos
o suporte ao nosso projeto.
Veremos então a página do nosso projeto com as informações específicas do mesmo, atualmente.
Agora que já temos o nosso projeto configurado vamos criar então o nosso arquivo appveyor.yml,
onde ficarão as nossas configurações de testes. Este arquivo é bem similar ao do Travis-CI em alguns
aspectos.
O conteúdo do nosso arquivo appveyor.yml com todas as alterações será o seguinte:
Adicionaremos a versão utilizada do NodeJS no campo environment do nosso arquivo de configu-
Dando suporte ao seu código em vários sistemas operacionais 73
ração.
1 ...
2 environment:
3 matrix:
4 - nodejs_version: "5.3.0"
5 ...
O campo platform será utilizado para descrever as plataformas utilizadas. Percebam que neste caso
ao invés de termos a diferenciação entre sistemas operacionais, temos entre plataformas do sistema
operacional (x86 e 64x).
Isso é interessante também caso haja a necessidade de ter uma noção da diferença de desempenho,
performance e outros aspectos da mesma aplicação em diferentes plataformas.
1 ...
2 platform:
3 - x86
4 - x64
5 ...
O campo install terá a lista dos nossos comandos iniciais. Perceba que o ps é um comando para
instalarmos o NodeJS com a especificada no arquivo. Após esta etapa limpamos o cache usando o
comando npm cache clean por medida de segurança, a fim de evitar possíveis falsos positivos nos
nossos testes e, terminado este comando, vamos então instalar as nossas dependências utilizando o
comando npm install.
1 ...
2 install:
3 - ps: Install-Product node $env:nodejs_version
4 - npm cache clean
5 - npm install
6 ...
O campo test_script terá a lista dos nossos comandos a serem executados no momento de execução
dos nossos testes. Estamos acessando diretamente a pasta node_modules e invocando os testes a
partir delas com o comando node_modules/.bin/istanbul cover node_modules/mocha/bin/_mo-
cha -- -R dot, pelo fato de utilizarmos o comando make test no nosso comando npm test.
Dando suporte ao seu código em vários sistemas operacionais 74
1 ...
2 test_script:
3 Run the test
4 - cmd: node_modules/.bin/istanbul cover node_modules/mocha/bin/_mocha -- -R dot
Como o nosso caso não é necessário a criação de um build, vamos adicionar a informação no nosso
arquivo com o valor off e vamos configurar o nosso build para ser finalizado o mais rápido possível
adicionando o campo fast_finish com o valor true.
1 build: off
2 matrix:
3 fast_finish: true
4 ...
O conteúdo final do nosso arquivo appveyor.yml com todas as alterações será o seguinte:
Percebam que neste caso temos a lista dos nossos build diferenciada por plataformas na página de
listagem.
Dando suporte ao seu código em vários sistemas operacionais 75
Com a nova integração testada, vamos então atualizar o arquivo README.md do repositório com
o badge do Appveyor. Com isto você verá uma imagem com o status do build, assim como o que já
inserimos anteriormente.
Perceba que temos duas tags neste trecho de código. Substitua estas informações da seguinte forma:
Por exemplo, baseado no repositório de exemplo, o nosso badge terá o seguinte conteúdo.
Como vocês puderam perceber adicionar suporte a vários sistemas operacionais e plataformas é uma
tarefa bastante simples com o Appveyor. Os próximos passos do livro serão mais voltados ao quesito
de melhorias na automação da checagem da nossa cobertura de código.
Dando suporte ao seu código em vários sistemas operacionais 76
Para verificarmos se ele está integrado no nosso repositório, basta digitarmos no nosso prompt/linha
de comando.
1 $ ./node_modules/.bin/istanbul help
56
http://gotwarlost.github.io/istanbul
57
https://pt.wikipedia.org/wiki/Engenharia_reversa
Dando suporte ao seu código em vários sistemas operacionais 77
O retorno será o mesmo da imagem abaixo. Podem reparar que agora temos algumas novas
informações no rodapé das mensagens dos testes, tais com porcentagens de linhas, funções, branches
e declarações de métodos, classes ou objetos.
Dando suporte ao seu código em vários sistemas operacionais 79
Percebam que agora temos uma nova pasta chamada coverage com alguns arquivos e todas estas
informações listadas na nossa linha de comando. Utilizaremos elas nos próximos passos para a
integração com o serviço Coveralls.
Dando suporte ao seu código em vários sistemas operacionais 80
O login é bem simples e você terá que habilitar a integração com o seu Github. Após esta etapa
você verá uma lista com todos os seus repositórios cadastrados no Github. Clique no botão ao lado
esquerdo do seu repositório listado e espere a mensagem "Off" transformar-se em "On".
59
https://coveralls.io/
Dando suporte ao seu código em vários sistemas operacionais 81
Adicionando repositórios
Perceba que, com o repositório ativado, temos agora um link para a página detalhes. Ao clicarmos
neste link seremos direcionados para uma página com todas as informações iniciais para o setup
do projeto no coveralls. Para a nossa solução usaremos a opção de adicionarmos a informação do
coveralls no arquivo .coveralls.yml.
Vamos então copiar este conteúdo da opção do arquivo na página de setup e criaremos o novo
arquivo no nosso projeto. Dentro do nosso repositório local, vamos digitar o seguinte comando via
prompt/linha de comando.
1 $ touch .coveralls.yml
Vamos abrir este arquivo no nosso editor e adicionaremos o conteúdo dentro deste arquivo. Após
Dando suporte ao seu código em vários sistemas operacionais 82
esta etapa adicionaremos o pacote NodeJS à nossa lista de dependências de desenvolvimento para
integrarmos a infraestrutura do coveralls ao nosso projeto digitando o seguinte comando.
Assim que enviarmos um novo código, podemos perceber que teremos as informações de porcen-
tagem de cobertura de código visível no site do coveralls, na área do nosso repositório. Com isto
podemos acompanhar todas as variações de cobertura de código, criamos validações e muito mais.
Depois disso podemos adicionar um novo badge com as informações do code coverage do nosso
projeto no arquivo README.md, contido no repositório do projeto. O padrão do badge é algo bem
simples:
1 [![Coverage Status](https://coveralls.io/repos/<nome-do-seu-usuario-ou-organizaç\
2 ão>/<nome-do-seu-repositório>/badge.svg?branch=master)](https://coveralls.io/r/<\
3 nome-do-seu-usuario-ou-organização>/<nome-do-seu-repositório>?branch=master)
Perceba que temos duas tags neste trecho de código. Substitua estas informações da seguinte forma:
Por exemplo, baseado no repositório de exemplo, o nosso badge terá o seguinte conteúdo.
1 [![Coverage Status](https://coveralls.io/repos/willmendesneto/build-checker/badg\
2 e.svg?branch=master)](https://coveralls.io/r/willmendesneto/build-checker?branch\
3 =master)
Após adicionarmos e salvarmos este código, o resultado final a ser renderizado será algo similar ao
da imagem a seguir.
Dando suporte ao seu código em vários sistemas operacionais 83
E com isto concluímos a nossa integração com o serviço do coveralls. Este é só um exemplo simples
de uma das várias funcionalidades deste serviço e recomendo fortemente que dêem uma lida na
documentação do coveralls60 para que vocês tenham uma maior sobre este serviço.
Caso queira saber mais sobre o PlatoJS, por favor acesse o repositório no Github do
projeto61
E feito esta etapa, o plato foi instalado localmente como dependência de desenvolvimento na nossa
pasta node_modules do nosso projeto. Nosso próximo passo é adicionar um novo comando NPM.
Agora nós teremos o comando code-analysis que vai acionar o plato ao nosso projeto.
60
https://coveralls.zendesk.com/hc/en-us
61
https://github.com/es-analysis/plato
Dando suporte ao seu código em vários sistemas operacionais 84
1 {
2 ...
3 "scripts": {
4 "start": "nodemon ./src/index.js -e js,json --watch ./src",
5 "test": "make test",
6 "code-analysis": "plato -r -d report src test"
7 },
8 ...
9 }
E após este comando será criada uma pasta de nome report com as informações da análise do nosso
repositório.
Dentro desta pasta teremos vários arquivos com as informações retornadas da análise do PlatoJS
que podemos visualizar mais detalhes acessando o arquivo index.html no nosso navegador.
Esta página terá informações de cada arquivo e gráficos mostrando dados como nível de complexi-
dade e linhas de código, como podemos ver na figura abaixo.
Dando suporte ao seu código em vários sistemas operacionais 85
Protoboard
Piezo
Piezo é um sensor que emite um sinal sonoro, tal como uma buzina. Este sinal pode ser criado em
uma aplicação Nodebots a partir de um valor numérico ou uma abstração de notas sonoras, o que
torna a sua manipulação mais simples.
Apêndice 87
Piezo
Resistores
Os resistores são vastamente utilizados na eletrônica, send um dos primeiros componentes eletrôni-
cos com o qual lidamos e um dos que mais utilizaremos. Eles são as bastante pequenos em forma de
pílula com listras na maioria das placas de circuito.
Um resistor é um componente eletrônico que limita o fluxo de elétrons dissipando energia sob a
Apêndice 88
forma de calor, pois a eletricidade tem que lutar para fluir através de algo com uma alta resistência.
Utilizando assim uma grande quantidade de energia e convertendo isso em calor.
Resistores
Light-emitting diode
Sensores
Dispositivo que converte dados do mundo real (analógica) em dados que um computador pode
entender usando ADC e convertendo os dados do formato Analógico para o Digital. Utilizaremos
sensores para detectarmos eventos ou mudanças no local e enviaremos para leitura na nossa
aplicação.
É o fio de entrada de condutor elétrico que possui a função de “aterrar” todos os dispositivos que
precisarem utilizar seu potencial como referência ou suas propriedades elétricas.
Em sistemas de potência, o terra possui as funções de referência elétrica para a tensão, sistemas de
proteção, controle para excesso de carga/energia e proteção de equipamentos.
Apêndice 90
Fios de condução
Fios isolados curto com extremidades sem capa de isolamento que usamos para conectar dois pontos
em um circuito ou protoboard.
Fios de condução
Botão
É um mecanismo simples para controlar alguns aspectos de uma máquina ou um processo. Ao clicar
no botão a corrente é liberada e ao soltar o botão a corrente é cancelada.
Botão
Próximos passos
Finalizando agora o conteúdo deste livro com alguns exemplos bastante didáticos já vemos o poder
do Javascript aliado a robótica em nossas aplicações. Estes são exemplos que podem ser incorporados
ao nosso cotidiano e ensinamentos para a execução de várias outras idéias que surgirão.
Espero que tenham gostado do conteúdo deste livro e dos exemplos tanto quanto eu tive o prazer
de compartilhar este conteúdo. Caso tenha dúvidas, questões ou até mesmo uma conversa, entre em
contato pelo email willmendesneto@gmail.com.
Muito obrigado!