Enviar archivo de audio/imagen Servidor Arduino Ethernet + Cliente Java por TCP

Hola buenas,

Os presento el proyecto que estoy realizando. Tengo una Ethernet Shield programada con un SERVER (conectada al router) y un código en java que hará de cliente (todavía a bajo nivel, enviar y recibir caracteres). Mi intención es que bajo una petición del cliente la placa arduino envíe una imagen o sonido por TCP y que el cliente la reproduzca o guarde.

Alguien tiene alguna idea de como afrontar este proyecto o algún tutorial o código de ejemplo? Me sería de gran ayuda pues llevo muchos días buscando y no encuentro nada relacionado.

Muchísimas gracias de antemano.

Saludos :slight_smile:

Hola,
siempre se puede intentar algo más difícil todavía, pero en principio te diría que Arduino tiene una memoria chiquita, y que los archivos de audio y vídeo suelen ser muy voluminosos. Esos archivos que quieres enviar con Arduino, ¿dónde estarían?

Hola Curro92, ante todo muchas gracias por contestar. :slight_smile:

Pues las imagenes/audios intentaría al principio que fueran de tamaño pequeño. Y estarán almacenadas en el slot SD de la Arduino Ethernet Shield.

Imagino que lo suyo sería enviarla en binario e ir almacenando en el buffer del cliente, pero no tengo muy claro ni como hacer y si se puede hacer así.

Graciaaas

Hola,
Para la comunicación serial tienes una función write() que envía datos binarios al puerto serie.

Puedes enviar byte a byte
Serial.write(val)

Y también puedes enviar un número (len) de bytes almacenados en una variable (buf)
Serial.write(buf, len)

http://arduino.cc/es/Serial/Write

Gracias :slight_smile:

Pues para ir haciendo pruebas, antes de meterme a fondo con la transferencia entre cliente-servidor, estoy haciendo un sketch para que el arduino copie una foto de la SD en otro archivo y así voy aprendiendo como funciona realmente.

Todavía no lo he comprobado ya que ahora mismo no tengo conmigo un tarjeta microSD :fearful:

Pero se me presentan varias dudas.

  1. Se pueden abrir dos archivos a la vez? (diría que no)
  2. Debe existir la segunda imagen? o se crea automáticamente?
  3. Es correcto el planteamiento que hago para copiarlo?

Imagino que si no se pueden abrir dos archivos a la vez, se debería hacer de otra forma (con buffers o algo).

Adjunto el código y a ver si me podéis ayudar

MUCHÍSIMAS GRACIAS!

#include <SD.h> 

void setup(){ 

  Serial.begin(9600);  



  //Serial.println("initializing sd card"); 
  pinMode(10,OUTPUT);          // CS pin of SD Card Shield 

  if (!SD.begin(10)) { 
    Serial.print("sd initialzation failed"); 
    return; 
  } 
  Serial.println("sd initialization done"); 
}  


void loop(){  


  File photoFile = SD.open("pic01.jpg");
  File photoFile2 = SD.open("pic02.jpg");

 


    if (photoFile) { 
    while (photoFile.available()) { 


      photoFile2.write(photoFile.read()); 
    } 

    photoFile.close(); 
    photoFile2.close();    
  }   

  else { 
    Serial.println("error copying photo"); 
  }

  Serial.println("Copyied photo");        
}

Hola,
no me entero lo que quieres hacer, ¿la idea no era enviar un fichero binario por internet? Para qué abres dos ficheros con arduino?

Hola Curro92,

Si, ese es el plan, pero para ir practicando quiero perfeccionar la lectura y escritura de imágenes en la SD, para ir haciendo pruebas. Ya que luego si falla algo, descartar que es por ese motivo.

Pero si, el objetivo final es hacer la transferencia de un server Arduino Ethernet a un cliente java.

Gracias :slight_smile:

Yo no buscaba exactamente lo que tu quieres, pero la idea es la misma.
Yo he probado a hacer un servidor con el arduino. Lo malo es que las páginas son muy sencillas porque el espacio de memoria es lo que es. Por eso me gustaría que las páginas web (al menos lo más gordo) estuviera en la memoria SD y que al cargar las páginas la mayor carga de información estuviera en la SD y desde el arduino son lo que se actualice (valores de las entradas digitales o similares).

He conseguido hacer una copia de una imagen en la SD. Os dejo el codigo. Ahora el siguiente paso es en lugar de guardarla en la SD, enviarla por SOCKET :slight_smile:

File FileFlor;
File FileFlor2;
byte buffer[500];


void setup(){

  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");


  FileFlor = SD.open("Flor.txt");


  if (FileFlor) {
    Serial.print("opening the img Flor.jpg..");


    Serial.println("done.");
  } 
  else {

    Serial.println("error opening Flor.txt");
  }

  if(SD.exists("Flor2.txt")){
    SD.remove("Flor2.txt");
    Serial.println("Eliminada");
  }

  if (FileFlor) {

    FileFlor2 = SD.open("Flor2.txt", FILE_WRITE);
    //Counter
    int i = 0;

    if(FileFlor2){
      while (FileFlor.available()>0) {

       	buffer[i] = FileFlor.read();
        //FileFlor2.write(FileFlor.read());
        Serial.println(i);
        
	if(i>500){ 
          FileFlor2.write(buffer,500);
          Serial.println("Copying to the memory..... ");  
          i=-1;
        }
       
        i++;
      }     
    
    }
    else{
      Serial.println("error opening Flor2.jpg");
    }
    Serial.println("Done copying");    
    FileFlor.close();
    FileFlor2.close();
  } 
}

void loop()
{
  // nothing happens after setup
}

Vale, despues de realizar la copia de un archivo con exito. Me tiré a la piscina para programar el cliente en java (android).

Tengo el protocolo implementado, pero tengo problemas con los tipos de variables entre arduino y java.

Resumiendo un poco el codigo, una vez hecha la conexión el cliente se queda a la espera de que le llegue el tamaño del primer buffer que enviará arduino.
Una vez recibido el tamaño, leo los datos y los almaceno en un buffer al que se le irán añadiendo todos los datos del archivo que más tarde, guardo en la SD del movil.

El problema está, en que por ejemplo, envio un tamaño = 500 y java lo interpreta como un numero totalmente distinto (8499834 por ejemplo). He utilizado diferentes formas para enviar: client.write(500), cliente.print(500)...

Y ya no se que hacer para que se entiendan el uno con el otro.

Si alguien me pudiera ayudar le estaría muy agradecido. Adjunto los dos codigos por si alguien ve algun error.

Gracias otra vez.

codigo arduino

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



File FileFlor;
byte buffer[500];
int TAM_MAX = 500;
int zero = 0;

// Introducir la dirección MAC, IP y numero de PUERTO para el SERVER

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Ya se verá
IPAddress serverIP(192,168,1,128); // Ya se verá
int serverPort=8888; // Ya se verá

// Iniciamos la libreria del server ETHERNET
EthernetServer server(serverPort);

void setup()
{

  Serial.begin(9600);
  // Iniciamos la conexion ethernet y el server:
  Ethernet.begin(mac, serverIP);
  server.begin();
  Serial.println("Server en MARCHA");//log
  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
}

void loop()
{
  // Escucha de clientes
  EthernetClient client = server.available();
  int tam;
  if (client) {

    //Declaro la variable string que contendrá lo que nos envie el cliente
    //String clientMsg ="";
    while (client.connected()) {
      if (client.available()) {
        FileFlor = SD.open("Archivo2.txt");

        if (FileFlor) {
          Serial.print("opening the img Flor.jpg..");
          Serial.println("done.");
        } 
        else {
          Serial.println("error opening Flor.jpg");
        } 


        if (FileFlor) {
          
          int i = 0;
               
          while (FileFlor.available()>0) {
            buffer[i] = FileFlor.read();
            
            Serial.println(i);
            
            //Envio tamaño
            client.print(TAM_MAX,DEC);
            
            
            if(i==TAM_MAX-1){ 
              
              //envio buffer con datos        
              client.write(buffer,TAM_MAX);
              Serial.println("Transfering to client..... ");  
              i=-1;
            }
            i++;
          }
          
          
          
          if(i>0){
      
            client.print(i);      
            for(int a=0; a<i ; a++){
              
              client.write(buffer[a]); 
            }       
          }
          //Enviamos que el tamaño es 0, para que se salga del bucle en el cliente.
          client.write(zero);
        }

        Serial.println("Done Transfer");    
        FileFlor.close();
      } 
    }
  }
  //Delay de espera para que el cliente reciba los datos
  delay(1);
  //Cerramos la conexión
  client.stop();
}

codigo JAVA

 public void onClick(View v) {
                              
                   try {
                     
                     Socket cs = new Socket("192.168.1.128", 8888);                                          
                     DataOutputStream Out = new DataOutputStream(cs.getOutputStream());
                     DataInputStream In = new DataInputStream(cs.getInputStream());
                     
                     Out.writeUTF(Lista.get(ListaObjetos.getCheckedItemPosition()));           
                     
                     //Recepcion de archivo en paquetes de tcp max bytes
                     ArrayList<Byte> buffer;
                    
                     buffer = new ArrayList<Byte>();
                     byte[] data;
                     
                    //Leo tamaño
                     int tam=In.readInt();
                                       
                     while(tam>0){                         
                        data = new byte[tam];
                        In.read(data);
                        for(int i=0; i<tam;i++){
                        buffer.add(data[i]);
                        }
                        tam=In.readInt();                        
                     }
                    
                     
                     In.close();
                     Out.close();
                     cs.close();
                     byte[] archivo =new byte[buffer.size()];
                     for(int i=0; i<buffer.size();i++){
                        archivo[i]=buffer.get(i);
                     }
                                                              
                     save_file(archivo,Lista.get(ListaObjetos.getCheckedItemPosition()));
                     
                 } catch (IOException ex) {
                     toastShow(ex.toString());
                     Logger.getLogger(PFC.class.getName()).log(Level.SEVERE, null, ex);
                 }              
                   
                 
                 
             }

Buenas estube leyando un poco todo el post y me parece bueno lo que haz hecho en tu lugar mandaria una cadena es decir un string y en java lo convertiria a numero para evitar esos problemas.

Saludos suete

Hola steve_182, supongo que ya lograste tu cometido.
Abras logrado enviar una imagen o audio a través de TCP??
O sigues atorado con el JAVA?? :relaxed: