Ethernet Shield + Arduino UNO + Android

Pessoal estou com um problema, não sei mais o que fazer , tentei de tudo... é o seguinte:
Tenho uma aplicação Android que acessa um Arduino Uno com Ethernet Shiled, porém, só consigo acessar e acionar um led se eu estiver na rede local, via internet eu não consigo. Já configurei no meu Router para o redirecionamento de pacotes para o endereço do Arduino "192.168.1.20", mas o Arduino não recebe os pacotes. Outra coisa , o meu Ethernet Shield é esse:

Minha Aplicação Arduino está configurada assim:

#include <SPI.h>
#include <Ethernet.h>

//define actions
#define action_none -1
#define action_out_all 0
#define action_mypin_up 1
#define action_mypin_down 2

// define network config
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xBE }; //physical mac address
byte ip[] = { 192, 168, 1, 20 }; // ip in lan -> cambialo pure
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
Server server(80); //server port
String readString = String(30); //string for fetching data from address

// arduino out
int pinOutRelay = 5;

// incoming GET command
String r_pinOutRelay_down = "GET /?out=5&status=0 HTTP/1.1";
String r_pinOutRelay_up = "GET /?out=5&status=1 HTTP/1.1";
String r_out_all = "GET /?out=all HTTP/1.1";

// current action
int current_action;

void setup(){
//start Ethernet
Ethernet.begin(mac, ip, gateway, subnet);

pinMode(pinOutRelay, OUTPUT);
digitalWrite(pinOutRelay, LOW);
//enable serial datada print
Serial.begin(9600);
current_action = -1;
}
void loop(){
current_action = -1;
// Create a client connection
Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 30)
{
//store characters to string
readString = readString + c;
}
//output chars to serial port
//Serial.print(c);
//if HTTP request has ended
if (c == '\n') {

Serial.print(readString);
// ****************************************************
if(readString.startsWith(r_pinOutRelay_up))
{
Serial.print("\n HIGH\n");
current_action = action_mypin_up;
}
else if(readString.startsWith(r_pinOutRelay_down))
{
Serial.print("\n LOW\n");
current_action = action_mypin_down;
}
else if(readString.startsWith(r_out_all))
{
Serial.print("\n ALL\n");
current_action = action_out_all;
}
else
{
Serial.print("\n None \n");
current_action = action_none;
}
// ****************************************************
// now output HTML data starting with standart header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
char buf[12];
switch(current_action)
{
case action_out_all:
client.print("{"ip" : "192.168.10.20", "devices" : [{ "type" : "gate", "name" : "caldaia", "out" : "");
client.print(pinOutRelay);
client.print(""}");
client.print("]}");
break;
case action_mypin_down:
digitalWrite(pinOutRelay, LOW);
client.print("{"status" : "low" , "out" : "");
client.print(pinOutRelay);
client.print(""}");
break;
case action_mypin_up:
digitalWrite(pinOutRelay, HIGH);
client.print("{"status" : "high" , "out" : "");
client.print(pinOutRelay);
client.print(""}");
break;
default:
current_action = action_none;
}
// ****************************************************
//clearing string for next read
readString="";
//stopping client
client.stop();
}
}
}
}
}

Minha aplicação Android executa o comando assim:

public final String executaGet(String url) {
Log.i(CATEGORIA, "Http.metodoGet: " + url);
try {
// Cria a URL
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();

// Configura a requisicao para get
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
conn.connect();

InputStream in = conn.getInputStream();

// String arquivo = readBufferedString(sb, in);
String arquivo = readString(in);

conn.disconnect();

return arquivo;
} catch (MalformedURLException e) {
Log.e(CATEGORIA, e.getMessage(), e);
} catch (IOException e) {
Log.e(CATEGORIA, e.getMessage(), e);
}
return null;
}

Para enviar os comandos para o Arduino eu envio pela WEB ou pelo Android da seguinte forma:

http://IP_externo:80/?out=5&status=1 ---------------> Para ligar o Led
http://IP_externo:80/?out=5&status=0 ---------------> Para desligar o Led

Se o meu computador estiver logado na rede executando os seguinte comandos, eu consigo ligar e desligar o Led, inclusive pelo android:
http://192.168.1.20:80/?out=5&status=1
http://192.168.1.20:80/?out=5&status=0

Alguém saberia me informar o motivo pelo qual eu não estou conseguindo acessar o Arduino via web ?

Obrigado.

O problema com certeza e no seu roteador, a porta 80 e para acessar a pagina de configuração do seu roteador rode seu aplicativo em outra porta por exemplo 8080 e faça o devido roteamento que vai funcionar!

Blz Kotch vou fazer esse teste , valeu !

Kotch , fiz o teste mas ainda não consigo enviar comandos para o Arduino, coloquei a porta 2376 ,estou tentando enviar dados para o Ethernet Shield da seguinte forma:

http://IP_Externo:2376/?out=8&status=1

Porém, não consigo enviar os comandos , acessando via chrome da a seguinte mensagem : Ops! O Google Chrome não conseguiu se conectar a...
Mas eu consigo acessar da seguinte forma:

http://192.168.1.107:2376/?out=8&status=1

sem problemas , o Led liga e desliga...

Mais alguma dica ?

Mas de que forma esta acessando de dentro ou fora da sua rede?

Não entendi bem o problema?
1-Quando voce esta na rede interna voce consegue conectar no ip interno?
2-Quando voce esta na rede interna voce não consegue conectar no ip externo?
3-Quando voce esta na rede externa voce consegue conectar no ip externo?
4-Seu ip é fixo ou dinamico?
5-tem um firewall bloqueando pelo acesso externo?

Se de uma forma acessa, de outra tambem irá funcionar, pois TUDO DEPENDE DE ROTEAMENTO!

É isso mesmo Kotch , é uma questão de roteamento...
1-Sim consigo perfeitamente.
2-Sim perfeitamente.
3-Sim , mas o problema é quando eu estou tentando acessar de fora para dentro , quando eu quero acessar do meu celular a minha rede interna.
4- Na minha rede interna os IPs são fixos e o meu "Ip Externo" é dinâmico.
5- Não , eu desabilitei o firewall no meu roteador.

O problema é acessar a minha rede interna quando eu estou usando o meu celular via 3G, esse é o problema.

valeu!

Já testou acessar de um IP interno o IP externo? Tipo, de um micro que esteja na rede interna, tentando conectar-se ao IP dinâmico externo?

Não use a porta 80, use 8080, como foi dito pelo Kotch, porque normalmente há firewalls dentro do provedor de acesso (seu Turbonet ou Speedy podem estar atrás de um firewall, isso que eu queria dizer)

Pois é neuron_upheaval , de dentro da minha rede eu consigo acessar o Arduino normalmente, tanto o IP interno , quanto o IP externo dinâmico, consigo acessar o Arduino e realizar todos os comandos, porém, quando estou acessando de fora da minha rede eu não consigo, no entanto, eu não testei acessar via outra porta, vou testar e falo para vocês o resultado.

Obrigado!

leodoidaum:
Pois é neuron_upheaval , de dentro da minha rede eu consigo acessar o Arduino normalmente, tanto o IP interno , quanto o IP externo dinâmico, consigo acessar o Arduino e realizar todos os comandos, porém, quando estou acessando de fora da minha rede eu não consigo, no entanto, eu não testei acessar via outra porta, vou testar e falo para vocês o resultado.

Obrigado!

Amigo, o problema parece estar mesmo nas configurações do seu roteador(configuração NAT para ser mais exato).
Você precisa direcionar todo o tráfego externo (IP_EXTERNO:Porta) para o ip interno (192.168.1.20)e na porta que você configurar(tenta configurar a 8080).

neuron_upheaval:
Já testou acessar de um IP interno o IP externo? Tipo, de um micro que esteja na rede interna, tentando conectar-se ao IP dinâmico externo?

Vai dar erro!
Nao vai conseguir pois a operadora, nao faz este roteamento!

Tem que que configurar o roteamento no seu modem adsl e nao use a porta 80 pois alem do bloqueio da operadora, a porta 80 e usada para configuracao do teu adsl entao quando conseguir se conectar da rede externa pra rede interna pela porta 80 vai cair na pagina de configuração do adsl!

Amigo, o problema parece estar mesmo nas configurações do seu roteador(configuração NAT para ser mais exato).
Você precisa direcionar todo o tráfego externo (IP_EXTERNO:Porta) para o ip interno (192.168.1.20)e na porta que você configurar(tenta configurar a 8080).

Qual o modelo do seu roteador ?
Entre nele e habilite o DMZ no IP do arduino e configure o arduino para a porta 8080.

Pessoal , me desculpe por demorar para responder , ultimamente tenho estado muito atarefado, porém , eu fiz o teste e não deu certo, fiz todos os roteamentos necessários, porem, não funciona , eu tentei na porta 8080 também e nada , só funciona se eu estiver via wifi , se eu estiver via 3G não funciona , aproposito , meu roteador é um linksys WRT120N ... eu uso ele e um modem adsl.
Eu não sei ao certo o que está errado , porem , acho que não é o meu roteador ... alguém tem mais alguma ideia ?

Obrigado!

Boa Tarde, aproveitando o tópico do amigo ai..

Estou desenvolvendo uma aplicação android do estilo da dele acima.. usando a pagina html gerada no arduino, consigo acionar e ver o status de sensores na mesma, e através da aplicação android que implementei, consigo acionar o relê através de uma variável ex: http://meuipoudns.com:8080/ligar, mas o que preciso realmente é conseguir obter o retorno na aplicação android do estado de uma porta OUTPUT.

Pela minha lógica, se conseguisse pegar o texto da pagina HTml na aplicação android, daria para tratar e verificar estado através de um botão refresh, que buscaria o conteúdo a cada click..

Se alguém puder me dar uma luz ai.. Agradeço!!

Olá Prezados,
tenho um UNO 2011 + Shield Ethernet, porém o Shield apresenta o seguinte problema, após implementar o código WebServer do exemplo da IDE ele funciona perfeitamente, porém ao desligar o cabo USB, e tentar ligar novamente o Shield não se comunica com o Roteador , ficando com os dois leds do conector RJ45 ligados e também os leds RX, FULLD, 1ooM, LINK e PWR, e é claro, não consigo pingar no mesmo, os led da porta do roteador também não dá sinal de vida. Tenho que ficar ligando e desligando o cabo USB, até que ele volta a funcionar. O que pode ser ?

O problema é a famosa CGNAT a minha operadora bloqueia o acesso de fora para dentro...

tbm estou com esse problema,

Leodoidaum !
Boa Tarde!

Posso te ajudar com o seu problema, pelo que vi não tem nada em haver com seu programa ou sua operadora(em parte com ela).

Seu problema esta em uma area que eu particularmente entendo mais do que programação.

Vamos lá, nenhuma operadora de Internet da acesso direto ao cliente. Só terá isso em contratos aonde o aceso é realizado via IP FIXO, ou mais conhecido como IP VÁLIDO.

Se voce quer acessar sua aplicação de fora para dentro voce deve ter um dominio que aponte para o seu IP de internet.

Esse IP de Internet, no seu caso é Dinamico e por isso não pode ser identificado de fora da sua casa.

Para isso acontecer voce deve ter um DDNS, sei que viu isso no seu roteador :slight_smile:

Para resolver seu caso faça o seguinte:

Primeiro no seu roteador configure uma porta que não seja de uso comum, tipo 80, 8080 e etc.
Use a que voce relatou. 2...

Crie uma regra para liberar o acesso a ela e direciona-la para o IP do arduino, tanto protocolo TCP como UDP.

Depois disso, voce acessa a internet e vai no SITE www.noip.com, lá faça um cadastro e crie um nome de dominio tipo DDNS.

Esse dominio DDNS ira verificar seu IP de internet de tempos em tempos e atualizará a base de dados dele, caso ele mude por ter sido resetado ou outro motivo, o NOIP irá atualizar como novo ip.
Eles tem uma ferramente que voce pode instalar no seu micro de casa e toda as vezes que voce ligar o micro ele faz a comparação e atualiza o IP se precisar.

Na criação do DDNS voce ira escolher um nome de Host , exemplo: "arduinoip" e selecionar uma extensão para o Dominio tipo ".ddns.net".
Tem varias extensões pode escolher a que voce quiser.

Após feito isso ele irá mostrar o ip cadastrado, e voce poderá comparar com o seu IP de internet para ver se esta igual.

Para acessar de fora voce deverá usar o nome de host/dominio que voce criou ok! tipo: "arduinoip.ddns.net" ou em alguns casos o "arduinoip.ddns.net:porta", aonde "porta" é a mesma que voce liberou.

Pronto voce consegue acessar seu IOT de boa.

Voce verá no NOIP que ele tem a versão gratuita, mas ela não faz atualização automatica para voce , a não ser pelo app instalado no micro, este micro tem que estar na sua rede interna.
Após mais ou menos 60 dias ele pede para voce verificar o nome do host novamente, de 60 em 60 dias para voce continuar a usar a versão gratis.

Espero ter ajudado! Duvidas fico a disposição.

Sou novo na area de programação , mas com bagagem de 35 anos na area de Redes.
Valeu!