Introdução
Essa é a parte 1 da série Localização aproximada via IP com ESP8266. Na parte 1 será desenvolvido um Web Client com ESP8266 onde o mesmo será capaz de fazer requisições HTTP GET e POST, recebendo sua localização aproximada e posteriormente enviando esses dados a um Web Server. Na parte 2 será desenvolvido um Web Server em Node.js que recebe a localização aproximada do ESP8266 e exibe em uma página do Google Maps.
O módulo ESP8266 é atualmente uma das plataformas mais populares entre makers para desenvolvimento de projetos conectados à Internet. Podemos encontrá-lo em projetos desde Acionamento de Eletrodomésticos via Web até Dispositivos de Assistência Médica Pessoal. Essa popularidade é devida ao seu baixo custo e facilidade de desenvolvimento, podendo ser integrado e programado usando a IDE Arduino. Neste artigo utilizaremos a versão ESP-01 da família ESP8266.

Em um mundo IoT onde hoje existem diversos desses dispositivos conectados à internet gerando uma quantidade inimaginável de dados, uma coisa interessante a se saber é a localização e origem desses dispositivos.
Neste artigo iremos mostrar como obter a geolocalização aproximada de um módulo ESP8266 conectado à Internet e enviar esses dados para um servidor que exibe uma página Web com Google Maps e um marcador na localização aproximada.
Recomenda-se fortemente a leitura do artigo escrito por Pedro Bertoleti, BeagleBone Black – Localização aproximada via IP, onde o autor obtém a geolocalização aproximada de uma Beaglebone Black via IP usando a linguagem Python.
Pré Requisitos
Para a reprodução deste artigo, é necessário ter:
- Um módulo WiFi ESP8266 ESP-01;
- Um roteador WiFi conectado à Internet;
- Noções de programação usando a IDE Arduino e suas bibliotecas;
- Noções do protocolo HTTP e seus métodos de requisição GET e POST;
- Noções de JSON.
Programando ESP8266 com IDE Arduino
Para possibilitar a programação do módulo ESP8266 usando a IDE Arduino, execute os seguintes passos:
- Abra a IDE Arduino
- Clique em File -> Preferences
- Adicione a seguinte URL no campo Additional Boards Manager URLs e clique OK
- Clique em Tools -> Board -> Bards Manager
- Encontre a placa esp8266 by ESP8266 Community e clique em instalar.
Assim teremos disponíveis as placas da linha ESP8266, suas bibliotecas e exemplos incluídos.
Funcionamento da API de Geolocalização via IP
Dentre alguns serviços da web que fornecem uma API de Geolocalização via IP, temos o ip-api.com. Além de ser free, é bem fácil de usar. Basta apenas enviarmos uma requisição HTTP GET (para testes pode-se usar cURL) para o link https://ip-api.com/json e receberemos o seguinte JSON como resposta:
$ curl -X GET https://ip-api.com/json
{
"as": "CLARO S.A.",
"city": "Artur Nogueira",
"country": "Brazil",
"countryCode": "BR",
"isp": "Virtua",
"lat": -22.5833,
"lon": -47.15,
"org": "Virtua",
"query": "177.194.xx.xxx",
"region": "SP",
"regionName": "Sao Paulo",
"status": "success",
"timezone": "America/Sao_Paulo",
"zip": "13160"
}
Usando o selecionador de itens, podemos especificar quais itens desejamos receber como resposta.

Selecionando apenas country,region,city,lat,lon,query, podemos fazer uma requisição GET no seguinte link:
Ou também usar a forma numérica para economizar largura de banda:
E receberemos do servidor o seguinte JSON:
{
"city": "Artur Nogueira",
"country": "Brazil",
"lat": -22.5833,
"lon": -47.15,
"query": "177.194.xx.xxx",
"region": "SP"
}
Implementando requisições HTTP no ESP8266
A biblioteca que possibilita ao ESP8266 se portar como um Web Client e fazer requisições HTTP é a ESP8266WiFi que pode ser incluída no código com ‘#include <ESP8266WiFi.h>’.
A função que faz a requisição HTTP GET para receber os dados de gelolocalização é a seguinte:
String makeGETlocation()
{
if ( !client.connect(IpApiHost, 80) ) {
Serial.println("connection ao ip-api.com falhou");
return "connection failed";
}
// Realiza HTTP GET request
client.println("GET /json/?fields=8405 HTTP/1.1");
client.print("Host: ");
client.println(IpApiHost);
client.println("Connection: close");
client.println();
// recebe o Header de resposta,
// cada linha do header termina com "\r\n", a última linha é vazia (“\r\n”)
while (client.connected()) {
String data = client.readStringUntil('\n'); Serial.println(data);
if (data == "\r") {
break;
}
}
// recebe os dados de geolocalização em formato JSON e guarda na variável data
String data = client.readStringUntil('\n');
Serial.println("Dados de geolocalização recebidos\n");
//Serial.println(data);
return data;
}
Primeiramente, tentamos conectar ao Host ip-api.com na porta 80, então fazemos uma requisição GET da seguinte maneira:
GET /json/?fields=8405 HTTP/1.1 Host: ip-api.com Conection: close <linha vazia>
Logo após, o servidor ip-api retorna com um Header (Cabeçalho). Lemos o Header até chegarmos na linha vazia “\r\n”.
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Content-Type: application/json; charset=utf-8 Date: Wed, 11 Jan 2017 13:10:22 GMT Content-Length: 111 Connection: close <linha vazia “\r\n”>
Após o Header lemos o JSON com os dados de geolocalização e imprimimos no console serial.
Requisitando Geolocalização via IP
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Date: Wed, 11 Jan 2017 13:10:22 GMT
Content-Length: 111
Connection: close
Dados de geolocalização recebidos
{"city":"Artur Nogueira","country":"Brazil","lat":-22.5833,"lon":-47.15,"query":"177.194.26.233","region":"SP"}
Para enviarmos o JSON recebido ao servidor, fazemos uma requisição POST no link ‘/location’ indicando o endereço e porta do servidor. A função que realiza essa tarefa é a seguinte:
void makePOSTlocation()
{
String location = makeGETlocation(); // guarda o JSON de geolocalização na variável location
if(!client.connect(rpiHost, 3000)) // aqui conectamos ao servidor
{
Serial.print("Could not connect to host: \n");
Serial.print(rpiHost);
}
else
{
// realiza HTTP POST request
client.println("POST /location HTTP/1.1");
client.println("Host: 192.168.0.24");
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(location.length());
client.println();
client.println(location); // enviamos o JSON ao servidor
}
}
Código Completo – Localização aproximada via IP com ESP8266
O código completo pode ser visto e analisado abaixo:
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
// Definições da rede Wifi
const char* SSID = "nome da rede";
const char* PASSWORD = "senha da rede";
// endereço IP local do Servidor Web instalado na Raspberry Pi 3
// onde será exibida a página web
const char* rpiHost = "192.168.0.24";
// servidor que disponibiliza serviço de geolocalização via IP
const char* IpApiHost = "ip-api.com";
WiFiClient client;
/*
* função que conecta o NodeMCU na rede Wifi
* SSID e PASSWORD devem ser indicados nas variáveis
*/
void reconnectWiFi()
{
if(WiFi.status() == WL_CONNECTED)
return;
WiFi.begin(SSID, PASSWORD);
while(WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println();
Serial.print("Conectado com sucesso na rede: ");
Serial.println(SSID);
Serial.print("IP obtido: ");
Serial.println(WiFi.localIP());
}
void initWiFi()
{
Serial.println("\nIniciando configuração WiFi\n");
delay(10);
Serial.print("Conectando-se na rede: ");
Serial.println(SSID);
Serial.println("Aguarde");
reconnectWiFi();
}
/*
* Função que realiza GET request no site ip-api.com
* Esse site disponibiliza uma API de geolocalização via IP
* A função retorna um JSON com dados de geolocalização
* Os dados de geolocalização são exibidos na pagina web em um Google Maps
*/
String makeGETlocation()
{
Serial.println("\nRequisitando Geolocalização via IP\n");
if ( !client.connect(IpApiHost, 80) ) {
Serial.println("connection ao ip-api.com falhou");
return "connection failed";
}
// Realiza HTTP GET request
client.println("GET /json/?fields=8405 HTTP/1.1");
client.print("Host: ");
client.println(IpApiHost);
client.println("Connection: close");
client.println();
// recebe o Header de resposta,
// cada linha do header termina com "\r\n", a ultima linha é fazia, ou seja, "\r\n" apenas
while (client.connected()) {
String data = client.readStringUntil('\n'); // lê uma linha até o "\n"
Serial.println(data);
if (data == "\r") { // a ultima linha do header é vazia, ou seja apenas "\r\n", se lermos até "\n", temos apenas "\r"
break;
}
}
// recebe os dados de geolocalização em formato JSON e guarda na variável data
String data = client.readStringUntil('\n');
Serial.println("Dados de geolocalização recebidos\n");
Serial.println(data);
return data;
}
/*
* Função que envia ao servidor a localização do NodeMCU
* função realiza um POST request ao servidor no link /location
* o servidor por sua vez exibe a localização do NodeMCU no Google Maps
*/
void makePOSTlocation()
{
String location = makeGETlocation(); // guarda o JSON de geolocalização na variável location
Serial.println("\nEnviando geolocalização ao servidor\n");
if(!client.connect(rpiHost, 3000)) // aqui conectamos ao servidor
{
Serial.print("Could not connect to host: \n");
Serial.print(rpiHost);
}
else
{
// realiza HTTP POST request
client.println("POST /location HTTP/1.1");
client.println("Host: 192.168.0.24");
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(location.length());
client.println();
client.println(location); // enviamos o JSON ao servidor
Serial.println("\nLocalização enviada com sucesso!");
}
}
void setup() {
Serial.begin(115200);
initWiFi();
makePOSTlocation();
}
void loop() {
}
Conclusão
Neste artigo foi desenvolvido um Web Client usando o módulo WiFi ESP8266 ESP-01 que utiliza da API do site ip-api.com para receber sua geolocalização aproximada via IP. Esse tipo de aplicação pode ser usada quando é necessário identificar a localização de um determinado dispositivo e quando não há possibilidade de usar um GPS no projeto.
Não deixe de ler a parte 2 desse artigo! Iremos mostrar os dados de geolocalização em um Google Maps!





Ótimo artigo, obrigado salvou meu dia
Boa tarde! Em primeiro lugar, muito obrigado pelos excelentes materiais que vocês disponibilizam! Bom, testei o código e obtive os dados. Mas surgiram alguns pontos que gostaria de ajuda para compreende-los. Expandi o código para inserir os dados obtido em tabela no BD MySql. Fiz os testes em 3 redes diferentes. a 1a em um ponto da NET na região da Av. Santa Catarina em Sao Paulo, a 2a pelo celular, uma linha da claro e uma 3a rede também da NET próximo a estacão Campo Limpo do Metro (Linha Lilas). No caso da 2a e 3a rede, fisicamente estava… Leia mais »
Hi, I’ve written a library to get position from Wi-Fi networks around using Google maps location API. You may have a look to it in https://github.com/gmag11/ESPWifiLocation
Hi Germán. Thanks! I will have a look and test your library.
Oi Giovanni. Nessa parte 1 do tutorial precisa criar alguma conta no site da API ?
Ou somente carregar o código completo com os dados wifi e RaspIP no Esp8266 ?
Essa parte que fala sobre o “o link https://ip-api.com/json” e o “Selecionador de itens” da API eu não entendi o que fazer com os links.
Aguardo resposta. Ótimo tuto!!
Boa tarde,
Primeiramente parabéns pelo Blog, conteúdo muito interessante e de simples compreensão. Porém, eu trabalho com programação e não intendo muito de eletrônica, e gostaria de programar alguns sensores do esp8266 nodemcu. Eu vi que alguns você pode conectar direto na placa sem o protoboard.
Segue um que eu vi na internet (RGB SMD LED Module 5050): https://www.ebay.com/itm/181307916806?_trksid=p2060353.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT
Gostaria de saber, o que eu deveria levar em consideração, quando for comprar algum sensor pra conectar direto no esp8266 nodemcu? Somente sensores com 3.3V para a alimentação são possíveis?
Olá Fábio. Obrigado pela leitura do artigo!
O NodeMCU e a família ESP em geral aceitam apenas níveis de 3,3V. Se não estou enganado os GPIOs suportam corrente máxima de 12mA.
Creio que esse modulo de LED SMD que vc indicou poderia ser usado com ESP sem problemas.
Muito bom esse artigo Giovanni Bauermeister, aguardando a segunda parte
Muito obrigado pela leitura Marcelo! Já saiu a segunda parte!