Servidor domotico con ethernet shield

para pasar más letras cambia por ejemplo:
if (*strbuf < 0x4f && *strbuf > 0x40){
a esto:
if (*strbuf < 0x58 && *strbuf > 0x40){
con esto tienes hasta la "V")
¿hasta cuanto puedes crecer el buffer? ¿por qué es tan crítico?

DRicote:

mira ese es solo una demo, en realidad mi servidor esta en casa y si prendido las 24Hs es un pentium III de 600mhz con 256Mb de ram sin teclados sin pantalla ni nada mas solo la torre conectada al router y listo, si te preocupa el consumo te digo q es muy muy poco.

pero si quieres tener un servidor externo lo puedes hacer perfectamente, si te fijas en mi pagina yo lo que hago es pasar un parametro por medio de GET o POST a la IP del arduino por ejemplo al seleccionar una zona se carga la IP y los botones tienen parametros genericos asi si precionas el boton de TV en la zona sala lo que haces es enviar un parametro a la IP 192.168.1.15/?acc1ON

si quieren se puede armar un topic para hacer un sistema domotico donde todos aportemos algo que les parece.

dejo algunos links donde e sacado info.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1278347111/0

ami este tema me interesa mucho, no solo prender y apagar las cosas, sino tmb recibir datos y poder programar las acciones.

cualquier cosa estoy por aqui ::slight_smile:

y mi pagina yo la puedo ver bien, el servidor es medio lento pero anda ;D

http://domotica23.260mb.com/

Usuario: user
Password: pass

Otra opción si quieres prescindir del uso de un PC entero para la tarea y poder montar un interface medio en condiciones es esta:

Mirate todos los enlaces de la izquierda que hacen referencia a LINKDUINO que es engancharle un Router por por puerto serie al arduino. Asi el router gestiona el servidor web desde una SD y el arduino solo se encarga de lo que se tiene que encargar.

El mas importante de todos es el ultimo
+LINKDUINO:DD-WRT + OPTWARE

pacojarcia:
Pues no se hasta donde se podría subir realmente el buffer, lo que si sé es que yo para hacer funcionar los 6 botones con dos "switch" como te comenté, tuve que subir el buffer a 1700, no funcionaba ni con mas ni con menos y por supuesto tuve que ir subiéndolo según fuí aumentando botones cuando empecé con ello.

Maverik:
Hola, no es por el consumo que pueda generar el ordenador las 24h, es que ya tuve uno hace tiempo como servidor de domótica por x10, camaras y alguna cosa mas, pero lo que pretendía con arduino es tener un sistema standalone y no preocuparme de nada mas que de alimentarlo y por supuesto que el tamaño reducido ayuda :wink:

Próbe a hacer una prueba en una html externa enviando por get al arduino y funcionó pero me devuelve la página del arduino, quiere decirse que si no funciona la del arduino no haría caso, supongo :-/ no?, bueno fue una prueba nada mas.

venomio:
Buenos enlaces, ya vi la página algun día, es del amigo Igor que también transita este foro, es una máquina el tio.

DRicote:
si el tamaño del arduino es algo q ayuda muxo.
no entiendo q pruebas hicistes, puedes explicar mejor? :-/

ok eso es lo q hace. prueba en poner este codigo en la pagina del arduino. lo que hace es regresart a la ultima pagina visitada.

client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("<head>");
          client.println("<meta http-equiv=Content-Type content=text/html; charset=utf-8 />");
          client.println("<title>Titulo de tu web</title>");
          client.println("</head>");
          client.println("<body>");
          client.println("<input type=button value=Atras onClick=javascript:history.back();>");
          client.println("</body>");

o tmb puedes cambiar el meta por este codigo que hace lo mismo pero automatico

<META HTTP-EQUIV= "Refresh"CONTENT=\"1;URL=javascript:history.back() ">

Pues le he borrado la web entera al arduino y le he puesto solo la redireccion con el meta que me has comentado y ya llevo 26 botones (on+off=52 en total) en servidor externo funcionando de maravilla, se puede hacer la web al gusto y sin problemas de saturar el buffer del enc28j60.

Por lo que tengo entendido, éste tiene un buffer de 8K, si la web con solo unos botones le ocupaba de 2 a 4K y la misma programación ya le metía mas, por eso se saturaba tan rápido...

Gracias tambien a pacojarcia que si no descubre lo de las letras hubiera sido imposible :wink:

Todo esto por el metodo get, alguien a probado con post?

Y otra cosa, antes cuando estaba la web en el arduino, se podía ver el estado de cada salida, como se podría visualizar esto en un servidor externo?

Lo que voy haciendo yo es una mera prueba en html, supongo que en php se le podría preguntar lo que tiene en memoria el arduino verdad?

También he conseguido meter en la eeprom el estado de encendido o apagado, así desde cualquier otro interface, ya sea un lcd, etc, se puede saber el estado real en cada momento.

Una buena forma que se me ha ocurrido es que el arduino con la shield de ethernet enviara esa info a una base de datos tipo mysql y así desde fuera (servidor externo) se pueden hace estadísticas y todo tipo de cosas.

Alguien ha conseguido conectar o sabe como se podría ,la shield basada en el enc28j60 a una base de datos tipo mysql?

Hola, la verdad es que soy nuevo en el tema arduino.. y me ha encantado como han llevado acabo este proyecto.. me parece espectacular.. solo que me queda una inquietud, sería posible montar esto en una placa Arduino Mega??, así para tener más puntos de control

Claro que es posible!, la nueva shield de ethernet con chip wiznet (la que lleva slot micro sd) ya es compatible con el mega, la anterior había que hacerla alguna modificación pero también he visto que la usaban.

Hola Dricote, muchas gracias por responder, sabes, estoy con algunas dudas frente a este proyecto..

Tengo clara la configuración de la página, para el envío de la información a la Arduino, pero no tengo muy claro como realizar la configuración en el arduino para que recepcione la información de la web. Hice un intento pero no me funciono :-[ :-[ :-[

lo que sucede es que yo solo quiero abrir unas puertas, solo ON, y luego darle un tiempo para cerrar, como las puertas magnéticas...

pero me confundí un poco, revisé el código de pacojarcia y vi como funcionaba.. y esta de maravillas con 6 botones, pero también realicé una web para comunicarla con el arduino ocupando datos por la URL..

estimado Dricote, hice una prueba tratanto de tomar los datos de la Web, pero no me es posible que funcione, por lo que lei, lograste realizar esa opción, para mi es la mejor, porque no cargas el código en el arduino, si no que puedes ocupar un web que sería ideal,

el código que revisé es para la wiznet, y tu tenias la ethernet con el enc28J60, que es lo que tengo en este minuto, una duemilanove y una ethernet shield con el enc28j60.. podria ver la perte de tu código donde recopilas la información de la web ???

yo envío los valores de la web vía GET action,

Muchas Gracias

Si te revisas el post desde el principio hallarás la respuesta (ya lo han mencionado varios compañeros), para enviar info a la shield de ethernet por GET no hace falta que sea un modelo u otro, funciona con las dos.

Y no he quitado el código si no, no haría nada, sólo he quitado la parte de html.

Saludos

hola. he adquirido hace un tiempo una ethernet shield. y la aplicacion sobre la que estais debatiendo es la que mas me interesa y apasiona como aplicacion.
Estais a años luz mia. Podriais indicarme ejemplos o paginas para ir adquiriendo conocimientos. porque los codigos que poneis no estan completos no.

gracias.

si, hice un ejemplo de web como la siguiente:

sin título

pero el código que cargo en la arduino no me funciona, ahora estoy en la Universidad, llegando a casa postiaré en código que cargo en la arduino. Si es posible me indiquen donde está el problema,

Muchas Gracias

Muchas Gracias Dricote, logré enviar los datos vía web con los ejemplos del foro, lo que si intente colocar un delay bajo el primer switch, funciona pero se tarda 14 seg aprox. en apagar y además la web se torna lenta.. a que se puede deber eso...????

dejo mi codigo

#include "etherShield.h"

static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
static uint8_t myip[4] = {192,168,0,15};
static char baseurl[]="http://192.168.0.15/";
static uint16_t mywwwport =80; // listen port for tcp/www (max range 1-254)

// Relay status. Start Off.
byte on_off1;
byte on_off2;
byte on_off3;
byte on_off4;
byte on_off5;
byte on_off6;

#define BUFFER_SIZE 1500
static uint8_t buf[BUFFER_SIZE+1];
#define STR_BUFFER_SIZE 22
static char strbuf[STR_BUFFER_SIZE+1];

EtherShield es=EtherShield();

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf, byte on_off1, byte on_off2, byte on_off3, byte on_off4, byte on_off5, byte on_off6);
int8_t analyse_cmd(char *str);

// 6 relays connected to output
#define SW1  2
#define SW2  3
#define SW3  4
#define SW4  5
#define SW5  6
#define SW6  7

void setup(){
Serial.begin(9600); //PACO para depurar el programa
  /*initialize enc28j60*/
   es.ES_enc28j60Init(mymac);
   es.ES_enc28j60clkout(2);
   delay(10);
        es.ES_enc28j60PhyWrite(PHLCON,0x880);
      delay(250);
      es.ES_enc28j60PhyWrite(PHLCON,0x990);
      delay(250);
      es.ES_enc28j60PhyWrite(PHLCON,0x880);
      delay(250);
      es.ES_enc28j60PhyWrite(PHLCON,0x990);
      delay(250);
        delay(100);
  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip,mywwwport);
  // Init outputs
       pinMode(SW1, OUTPUT);
       digitalWrite(SW1, LOW);  // switch off LED
       pinMode(SW2, OUTPUT);
       digitalWrite(SW2, LOW);  // switch off LED
        pinMode(SW3, OUTPUT);
       digitalWrite(SW3, LOW);  // switch off LED
        pinMode(SW4, OUTPUT);
       digitalWrite(SW4, LOW);  // switch off LED
        pinMode(SW5, OUTPUT);
       digitalWrite(SW5, LOW);  // switch off LED
        pinMode(SW6, OUTPUT);
       digitalWrite(SW6, LOW);  // switch off LED
}

void loop(){
  uint16_t plen, dat_p;
  int8_t cmd;

// Ethernet Mode
  plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

  if(plen!=0){  /*plen will ne unequal to zero if there is a valid packet (without crc error) */
              // arp is broadcast if unknown but a host may also verify the mac address by sending it to a unicast address.
            if(es.ES_eth_type_is_arp_and_my_ip(buf,plen)){
              es.ES_make_arp_answer_from_request(buf);
              return;    }
            // check if ip packets are for us:
            if(es.ES_eth_type_is_ip_and_my_ip(buf,plen)==0){return;}
            if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
                    es.ES_make_echo_reply_from_request(buf,plen);
                    return;    }
            
            // tcp port www start, compare only the lower byte
      if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==mywwwport){
             if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){
                     es.ES_make_tcp_synack_from_syn(buf); // make_tcp_synack_from_syn does already send the syn,ack
                     return;}
             if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
                    es.ES_init_len_info(buf); // init some data structures
                    dat_p=es.ES_get_tcp_data_pointer();
                    if (dat_p==0){ // we can possibly have no data, just ack:
                            if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){es.ES_make_tcp_ack_from_any(buf);}
                            return;}
                    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
                            // head, post and other methods for possible status codes see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                            plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
                            goto SENDTCP;}
                    // If "get /" without parameters
                       if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
                            plen=print_webpage(buf, on_off1, on_off2, on_off3, on_off4, on_off5, on_off6);
                            goto SENDTCP;}
                    cmd=analyse_cmd((char *)&(buf[dat_p+5]));
                    
                    // Process commands
                    switch (cmd) {
                    case 'A':      //PACO: cambio los números por letras
                            on_off1=1;
                              digitalWrite(SW1, HIGH); // switch on LED1
                            delay(7000);
                            digitalWrite(SW1, LOW); 
                            break;
                    case 'B':
                            on_off1=0;
                                 digitalWrite(SW1, LOW);  // switch off LED1
                            break;
                    case 'C':
                            on_off2=1;
                              digitalWrite(SW2, HIGH);  // switch on LED2
                            break;
                    case 'D':
                            on_off2=0;
                              digitalWrite(SW2, LOW);  // switch off LED2
                            break;
                    case 'E':
                            on_off3=1;
                              digitalWrite(SW3, HIGH);  // switch on LED3
                            break;
                    case 'F':
                            on_off3=0;
                              digitalWrite(SW3, LOW);  // switch off LED3
                            break;
                    case 'G':
                            on_off4=1;
                              digitalWrite(SW4, HIGH);  // switch on LED4
                            break;
                    case 'H':
                            on_off4=0;
                              digitalWrite(SW4, LOW);  // switch off LED4
                            break;
                    case 'I':
                            on_off5=1;
                              digitalWrite(SW5, HIGH);  // switch on LED5
                            break;
                    case 'J':
                            on_off5=0;
                              digitalWrite(SW5, LOW);  // switch off LED5
                            break;
                    case 'K':
                            on_off6=1;
                              digitalWrite(SW6, HIGH);  // switch on LED6
                            break;
                    case 'L':
                            on_off6=0;
                              digitalWrite(SW6, LOW);  // switch off LED6
                            break;                
                        }
                    plen=print_webpage(buf, on_off1, on_off2, on_off3, on_off4, on_off5, on_off6);
                    
          SENDTCP:  es.ES_make_tcp_ack_from_any(buf); // send ack for http get
                    es.ES_make_tcp_ack_with_data(buf,plen); // send data      
    } } } } 


 // The returned value is stored in the global var strbuf
    uint8_t find_key_val(char *str,char *key)
    {
            uint8_t found=0;
            uint8_t i=0;
            char *kp;
            kp=key;
            while(*str &&  *str!=' ' && found==0){
                    if (*str == *kp){
                            kp++;
                            if (*kp == '\0'){
                                    str++;
                                    kp=key;
                                    if (*str == '='){ found=1;}
                            }
                    }else{kp=key;}
                    str++;
            }
            if (found==1){
                    // copy the value to a buffer and terminate it with '\0'
                    while(*str &&  *str!=' ' && *str!='&' && i<STR_BUFFER_SIZE){
                            strbuf[i]=*str;
                            i++;
                            str++;}
                    strbuf[i]='\0';
            }
            return(found);
}


int8_t analyse_cmd(char *str)
{      int8_t r=-1;
         if (find_key_val(str,"cmd")){
                if (*strbuf < 0x4f && *strbuf > 0x40){   //PACO antes era:   if (*strbuf < 0x3a && *strbuf > 0x2f) ahora permito de la 'A' a la 'N'
                        // is a ASCII number, return it
                        r=*strbuf;               // PACO antes era:   r=(*strbuf-0x30);  ahora esto 40 A->0 ; B -> 1 ; ....
                }
        }
        return r;
}


uint16_t print_webpage(uint8_t *buf, byte on_off1, byte on_off2, byte on_off3, byte on_off4, byte on_off5, byte on_off6)
{       int i=0;
        uint16_t plen;
        plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
        return(plen);
}

Desde hace algún tiempo iniciamos un sub-proyecto de OpenDomo (http://opendomo.org) basado en domótica sobre Arduino, al que bautizamos como Domino. Este sub-proyecto consiste en un firmware para Arduino que convierte la placa en una plataforma de automatismos, fácilmente programable y con una gran variedad de funciones, tal como podéis ver en la página oficial del proyecto: http://es.opendomo.org/domino

Uno de los próximos pasos a seguir es adaptar este firmware para dar soporte al Ethernet Shield de Arduino, pero al no disponer del dispositivo no lo hemos podido llevar a cabo aún. Si en este foro hay algún usuario interesado en usar Arduino como elemento de control domótico en red, tal vez quiera echar un vistazo a las posibilidades de Domino, ya que podría serle de utilidad.

Por ahora, la utilidad del puerto Ethernet está planteada como conexión por socket, emulando el actual puerto USB, pero tal vez podamos estudiar la posibilidad de incorporar algun soporte básico para HTTP más adelante, en cuanto podamos verificar su funcionamiento.

Hola a todos,

es mi primer mensaje en el foro, he estado siguiendo este post y la verdad es que me ha parecido muy interesante. Estoy usando la shield con chip de Wiznet 5100 y he intentado compilar el codigo de Maveric sin resultado positivo. Por cierto,estoy utilizando la version 021 de arduino.
Al principio me solicita la libreria SIP y una vez cargada, al compilar, me da los siguientes errores:

TEST_ETH_1.cpp: In function 'void loop()':
TEST_ETH_1:59: error: 'class String' has no member named 'append'
TEST_ETH_1:63: error: 'class String' has no member named 'contains'
TEST_ETH_1:84: error: 'class String' has no member named 'contains'
TEST_ETH_1:89: error: 'class String' has no member named 'contains'
TEST_ETH_1:94: error: 'class String' has no member named 'contains'
TEST_ETH_1:99: error: 'class String' has no member named 'contains'
TEST_ETH_1:104: error: 'class String' has no member named 'contains'
TEST_ETH_1:109: error: 'class String' has no member named 'contains'
TEST_ETH_1:114: error: 'class String' has no member named 'contains'

Alguna ayuda de porque puede estar ocurriendo esto?

Un saludo y gracias de antemano.
2torr

OK,
pues ya que no hay respuestas me contesto yo...Después de echarle un poco de tiempo en pruebas y demás, he conseguido salvar los dos problemas que tenía con el "contains" y el "append" que después de la versión del IDE 019 no funcionan. A partir de esta versión (019) la librería Strings se ha incorporado en el nucleo y hay funciones que no valen, por lo que hay que re-adaptar el código.

Si hay alguien interesado que pregunte.

Saludos.

si no me equivoco contais se sutituye por
if (strstr(lineaDeCaracteres,"buscar"));

donde lineaDeCaracteres es la cadena de caracteres y "buscar" es donde irian los caracteres que queremos buscar (entre " " ).