Enviar datos Arduino Ethernet shield

Hola a todos,

acabo de empezar con Arduino y tengo una Duemilanove con una Ethernet Shield con chip WIZ5100, todo de Libelium. Quiero enviar datos a un servidor java que tiene un socket en modo servidor a la escucha de conexiones. Esto me funciona si le envio datos desde otro programa java, pero no desde arduino. El código de socket servidor java es el siguiente:

import java.io.;
import java.net.
;
public class ServerSideSocket {
public static void main (String[] args) throws Exception{
// bucle infinito Ctrl+C para fin
ServerSocket ss = new ServerSocket(111);
System.out.println(" El server escucha por " +InetAddress.getLocalHost() + " a través del puerto " + ss.getLocalPort());
while (true) {
Socket s = ss.accept();//espera al cliente
DataInputStream dis = new DataInputStream(s.getInputStream());
String message = dis.readUTF();// wait for client to send
System.out.println(message);
dis.close();
}
}
}

El código cliente java es este:

import java.io.;
import java.net.
;
public class ClientSideSocket {
public static void main (String[] args) throws Exception {
if (args.length != 3) {
System.out.println(" Formato: java ClientSide Hostname port mensaje");
System.exit(0);
}
String serverName = args[0];
int serverPort = Integer.parseInt(args[1]);
String message = args[2];
Socket s = new Socket(serverName, serverPort);
// espera que el servidor acepte
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(message);
dos.close();
}
}

Y el código arduino es el siguiente:

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte server[] = { 192, 168, 1, 13 };

Client client(server, 111);

void setup(){
Ethernet.begin(mac, ip);
Serial.begin(9600);

delay(1000);

Serial.println("connecting...");

if (client.connect()) {
Serial.println("connected");
}
else {
Serial.println("connection failed");
}
}

void loop(){
if (client.connected()) {
client.println("mensaje desde arduino");
client.stop();
}
}

Con el Wireshark he visto que arduino sí envia paquetes al servidor, pero parece que no se entiende con Java. ¿Alguien me puede ayudar?

Gracias de antemano y un saludo,

Sigo probando, pero no doy con la solución de recibir mensajes desde arduino hacia java a través de un puerto y una IP. Abro un socket en un puerto que está a la escucha en el servidor(PC) y desde arduino pruebo a hacer la conexión con client.connect() pero no llega a conectarse. He revisado la configuración de red, el puerto,... y ya no sé que más puedo revisar... ¿Qué hace exactamente la función connect de la clase Client? En teoría realiza una conexión a una IP y a un puerto que esté a la escucha, ¿no? Soy novato en estos temas y ando perdido. ¿Algún consejo?

Gracias,

Supongo que ya habrás visto ésta página:

Pero fíjate en el client.available()

No sé que decirte ya que no tengo la ethernet shield ni he programado nada parecido.

Un saludo

Gracias por contestar chiva,

Sí, ya había visto el constructor. El tema está en que nunca entra en el if porque la función connect() no devuelve verdadero nunca. No sé porque no conecta.

Hola amroth.

Yo tampoco he probado la ethernet shield aunque tengo muchas ganas...

Supongo que en la parte del PC que escucha, habrás desactivado firewall y demás software que pueda interferir la conexión no? Es solo una idea....

Saludos, Pakoff.

Gracias por contestar Pakoff, esto fué de lo primero que comprobé. Utilizo Windows 7 y desde otro ordenador ejecutando el cliente de sockets java me funciona correctamente. El problema lo tengo con la función connect(), que no conecta con el puerto donde está escuchando el socket java, en cambio si que me funciona el ejemplo de Web Client. No sé que es lo que hace la función connect() que no se entiende con mi programa java...

Para mandar datos por Internet desde Arduino, ¿se hace siempre a través de peticiones http? Los ejemplos de la Ethernet Shield que he visto por Internet son de este tipo.

Un saludo,

Hola amroth.

Me paso algo similar, en mi caso lo solucione incorporando el gateway, dado que salia por un router.

byte gateway[] = { 192, 168, 100, 2 }; //your router's IP address
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask of the network

A proposito te hago una consulta, estas usando Ethernet2 como libreria o la standard?

Hola Mustang, uso la librería estándar. El tema de informar la puerta de enlace y mascara de subred no creo que sea, ya que el ejemplo de webclient que conecta a una web y la lee entera, por lo que no creo que sea por esto.

Gracias por contestar y un saludo,

Puede que tengas que cerrar la conexion para abrir luego otra (no esta demas cerrar las cosas)

if (client.connect()) {
Serial.println("connected");
client.stop();
}

Y PON LA NETMASK !!!

byte subnet[] = { 255, 255, 255, 0 };
byte gateway[] = { 192, 168, 0, 251 }; // esto si quieres

Ethernet.begin(mac, ip, gateway, subnet);

Puedes probar a enviar un mail por smtp y veras si va... (con gateway claro)

Para enviar un mail tengo algo asi. (faltan las variables) :wink:

byte smtpserver[] = { 213, 4, 149, 225 }; // terra

Client client(smtpserver, 25);

if (client.connect())
{
client.print("HELO ");
client.println(origen); // dice hola al servidor
delay(500);
client.println("AUTH LOGIN"); // comienza la autentificacion
delay(500);
client.println(usuario); // en BASE64
client.println(pass); // en BASE64
delay(500);
client.print("MAIL From: ");
client.println(origen);
client.print("RCPT To: ");
client.println(destino);
client.println("DATA");
client.print("From: ");
client.println(origen);
client.print("To: ");
client.println(destino);
client.print("Subject: ");
client.println(asunto);
client.println("");
delay(500);
client.println(""); // comienzo del mensaje
client.println(cuerpo);
client.println("");

////// client.println ...... texto del correo

client.stop();
enviado=true;
}
else
{
client.stop(); // error, lo reintentara
enviado=false;
}

Suerte!!!!

Hola diegocr, he probado lo que me comentas y sigo igual. El tema es que no se llega a conectar, ya que nunca entra en el if(no se cumple nunca). De java a java me funcionan correctamente el envío de mensajes a través de sockets, pero desde arduino a un programa java esperando conexiones no.

¿Alguna idea más?

Muchas gracias y un saludo,

Pues con este telnet a mi router el if se cumple, y con un netstat me dice que la conexion esta establecida. De java ni idea :-/

connecting...
connected
connecting...
connected
connecting...
connected
connecting...
connected

root@ROUTER:~# netstat -n |grep :23
tcp 0 0 192.168.0.251:23 192.168.0.201:1048 ESTABLISHED
tcp 0 2 192.168.0.251:23 192.168.0.77:50423 ESTABLISHED

#include <Ethernet.h>

byte mac[] = { 0x00, 0xFF, 0x12, 0xEF, 0xE4, 0xFF };
byte ip[] = { 192, 168, 0, 201 };
byte gateway[] = { 192, 168, 0, 251 };
byte subnet[] = { 255, 255, 255, 0 };

byte server[] = { 192, 168, 0, 251 };

Client client(server, 23);

void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
Serial.begin(115200);

delay(1000);

}

void loop(){

Serial.println("connecting...");

if (client.connect())
{
Serial.println("connected");
delay(5000);
client.stop();
}
else {
Serial.println("connection failed");
}

}

He conseguido dar un paso... Consigo conexiones a nivel de socket desde un programa java a un server en arduino y este es el código del cliente java:

public class ClientSideSocket {
      public static void main (String[] args) throws Exception {
            if (args.length != 3) {
                  System.out.println(" Formato: java ClientSide Hostname port mensaje");
                  System.exit(0);
            }
            String serverName = args[0];
            int serverPort = Integer.parseInt(args[1]);
            String message = args[2];
            Socket s = new Socket(serverName, serverPort);
            //      espera que el servidor acepte
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            dos.writeChars(message);
            dos.close();
      }

El servidor que corre en arduino es este:

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };

Server server(9002);

void setup()
{
Ethernet.begin(mac, ip);
server.begin();
Serial.begin(9600);
}

void loop()
{
Client client = server.available();
if (client) {
Serial.println();
Serial.println("Se ha conectado un cliente");
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.print(c);
}
}
delay(1);
client.stop();
}
}

Y me ha funcionado a la primera, ¿por qué no consigo hacerlo al revés? es decir, que sea el arduino quien se conecte al un socket servidor java.

¿Nadie ha hecho transmitir a arduino con la ethernet shield hacia un servidor que no sea http? La cuestión es que las conexiones a servidores http con arduino me funcionan, pero hacia el que creo en java no... y el servidor java funciona correctamente porque desde el mismo cliente java que muestro arriba me conecta.

A ver si alguien me muestra un poco de luz en este asunto...

Un saludo a todos,

Óscar

Hola!

Esta claro que el pseudo-C de arduino y java no se estan entendiendo como debieran... En una ocasión recuerdo que tuve muchísimos problemas para conectar un cliente en c a un server en java y al final conseguí saber a qué se debía: el cliente c solicitaba la conexión al puerto por el protocolo UDP mientras que java servía en TCP y llegaba, enviaba paquetes y no conectaba... No se si tu problema será ese pero eso es lo único que te puedo decir sobre el tema...

Siempre puedes probar a hacer pruebas, primero intentar conectar arduino a un socket de un servidor en C, y si esto sale bien, consulta las referencias de java para forzar que sirva el socket en UDP o, si puedes, en ambos protocolos.

Espero haberte ayudado, ya nos contarás!! Un saludo!! :wink:

Hola a todos,

Sólo comentar que conseguí recibir cadenas de texto a la primera creando el servidor de socket en C#. Por si alguien se está peleando con JAVA y Arduino.

Un saludo,