naNode web configuration sketch

Hi,

 

I did a small web configuration sketch (network and API)  that saves settings to EEPROM.

 

Give it a try.

 

 

#include <EtherCard.h>

//#include <Ports.h>

#include <avr/eeprom.h>

 

#define DEBUG   1   // set to 1 to display free RAM on web page

#define SERIAL  1   // set to 1 to show incoming requests on serial port

 

#define CONFIG_EEPROM_ADDR ((byte*) 0x10)

 

// configuration, as stored in EEPROM

struct Config {

  // ethernet interface mac address - must be unique on your network

byte usedhcp;

byte mymac[6] ;

byte ip[4];

byte mask[4];

byte gateway[4];

byte dns[4];

char domain[32];

char api[64];

byte valid; // keep this as last byte

} config

= {

  // The default values

  1,

  { 0x74,0x69,0x69,0x2D,0x30,0x31 },

  {192,168,2,2},

  {255,255,255,0},

  {192,168,2,1},

  {192,168,2,1},

  "yourdomain.com",

  "/~hariabql/sql_datalog.php?action=insert&uid=777&",

  253

};

 

 

 

static BufferFiller bfill;  // used as cursor while filling the buffer

 

byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

 

byte Ethernet::buffer[1000];   // tcp/ip send and receive buffer

 

static void loadConfig() {

    for (byte i = 0; i < sizeof config; ++i)

        ((byte*) &config)[i] = eeprom_read_byte(CONFIG_EEPROM_ADDR + i);

    if (config.valid != 253) {

        config.valid = 253;

        config.mymac[1] = 0x74; //{ 0x74,0x69,0x69,0x2D,0x30,0x31 };

        config.mymac[2] = 0x69;

    }

}

 

static void saveConfig() {

    for (byte i = 0; i < sizeof config; ++i)

        eeprom_write_byte(CONFIG_EEPROM_ADDR + i, ((byte*) &config)[i]);

}

 

#if DEBUG

static int freeRam () {

  extern int __heap_start, *__brkval; 

  int v; 

  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 

}

#endif

 

static void gotPinged(byte* ptr) {

    ether.printIp(">>> ping from: ",ptr);

}

 

 

void setup(){

#if SERIAL

    Serial.begin(9600);

    Serial.println("\n[etherNode]");

#endif

 

    loadConfig();

    

    if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) 

      Serial.println( "Failed to access Ethernet controller");

      

    if (false) {

    if (!ether.dhcpSetup())

      Serial.println("DHCP failed");

    }

    else

    if (!ether.staticSetup(config.ip,config.gateway,config.dns))

      Serial.println("Static IP failed");

     

   

#if SERIAL

    ether.printIp("My IP: ", ether.myip);

//    ether.printIp("Netmask: ", ether.mymask);

    ether.printIp("GW IP: ", ether.gwip);

    ether.printIp("DNS IP: ", ether.dnsip);       

#endif

 

/*

    if (!ether.dnsLookup(config.domain))

      Serial.println("DNS lookup of host failed");

#if SERIAL

    ether.printIp("Server IP: ", ether.hisip);

#endif

//ether.parseIp(ether.hisip,"192.168.1.200"

 

*/

    ether.registerPingCallback(gotPinged);

 

}

 

 

char okHeader[] PROGMEM = 

    "HTTP/1.0 200 OK\r\n"

    "Content-Type: text/html\r\n"

    "Pragma: no-cache\r\n"

;

 

static void homePage(BufferFiller& buf) {

 

    buf.emit_p(PSTR("$F\r\n"

        "<meta http-equiv='refresh' content='5'/>"

        "<title>Nanode home page</title>" 

        "naNode configuration page "

            "- <a href='c'>network</a> - <a href='a'>API</a>"), okHeader);

        

    long t = millis() / 1000;

    word h = t / 3600;

    byte m = (t / 60) % 60;

    byte s = t % 60;

    buf.emit_p(PSTR(

        "</pre>"

        "<br>Uptime is $D$D:$D$D:$D$D"), h/10, h%10, m/10, m%10, s/10, s%10);

#if DEBUG

    buf.emit_p(PSTR(" ($D bytes free)"), freeRam());

#endif

}

 

static int getIntArg(const char* data, const char* key, int value =-1) {

    char temp[10];

    if (ether.findKeyVal(data + 7, temp, sizeof temp, key) > 0)

        value = atoi(temp);

    return value;

}

 

static char* getArg(const char* data, const char* key, int value =-1) {

    char temp[64];

    if (ether.findKeyVal(data + 7, temp, sizeof temp, key) > 0)

    return temp;

}

 

 

static void configPage(const char* data, BufferFiller& buf) {

    // pick up submitted data, if present

    if (data[6] == '?') {

      

        //IP

        byte i1 = getIntArg(data, "i1");

        byte i2 = getIntArg(data, "i2");

        byte i3 = getIntArg(data, "i3");

        byte i4 = getIntArg(data, "i4");

 

        //Gateway

        byte g1 = getIntArg(data, "g1");

        byte g2 = getIntArg(data, "g2");

        byte g3 = getIntArg(data, "g3");      

        byte g4 = getIntArg(data, "g4");  

        

        //DNS

        byte d1 = getIntArg(data, "d1");

        byte d2 = getIntArg(data, "d2");

        byte d3 = getIntArg(data, "d3");      

        byte d4 = getIntArg(data, "d4");                

 

 

        if ((i1 >= 0 && i1 <= 255 && i2 >= 0 && i2 <= 255 && i3 >= 0 && i3 <= 255 && i4 >= 0 && i4 <= 255) 

        && (g1 >= 0 && g1 <= 255 && g2 >= 0 && g2 <= 255 && g3 >= 0 && g3 <= 255 && g4 >= 0 && g4 <= 255)        

        && (d1 >= 0 && d1 <= 255 && d2 >= 0 && d2 <= 255 && d3 >= 0 && d3 <= 255 && d4 >= 0 && d4 <= 255)) 

        {

            // store values as new settings

            

            config.ip[0]=i1; config.ip[1]=i2; config.ip[2]=i3; config.ip[3]=i4;

            config.gateway[0]=g1; config.gateway[1]=g2; config.gateway[2]=g3; config.gateway[3]=g4;

            config.dns[0]=d1; config.dns[1]=d2; config.dns[2]=d3; config.dns[3]=d4;

            

            saveConfig();

            loadConfig();

 

            // redirect to the home page

            buf.emit_p(PSTR(

                "HTTP/1.0 302 found\r\n"

                "Location: /\r\n"

                "\r\n"));

            return;

        }

    }

    // else show a configuration form

    buf.emit_p(PSTR("$F\r\n"

        "<h3>naNode network settings</h3>"

        "<form>"

          "<p>"      

            "IP   <input type=text name=i1 value='$D' size=3>.<input type=text name=i2 value='$D' size=3>.<input type=text name=i3 value='$D' size=3>.<input type=text name=i4 value='$D' size=3> <br>"

            "GW   <input type=text name=g1 value='$D' size=3>.<input type=text name=g2 value='$D' size=3>.<input type=text name=g3 value='$D' size=3>.<input type=text name=g4 value='$D' size=3> <br>"

            "DNS  <input type=text name=d1 value='$D' size=3>.<input type=text name=d2 value='$D' size=3>.<input type=text name=d3 value='$D' size=3>.<input type=text name=d4 value='$D' size=3> <br>"

          "</p>"

          "<input type=submit value=Set> <input type=button value=Back onclick='history.go(-1)'>"

        "</form>"),okHeader,

        config.ip[0],config.ip[1],config.ip[2],config.ip[3],

        config.gateway[0],config.gateway[1],config.gateway[2],config.gateway[3],

        config.dns[0],config.dns[1],config.dns[2],config.dns[3] );

}

 

 

 

static void apiPage(const char* data, BufferFiller& buf) {

    // pick up submitted data, if present

    if (data[6] == '?') {

      

      char* temp=getArg(data, "domain");

      

      for(int i=0;i<sizeof(config.domain);i++) {

           config.domain[i]=temp[i] ;

      }     

 

      temp=getArg(data, "api");

      ether.urlDecode(temp);

       

      for(int i=0;i<sizeof(config.api);i++) {

           config.api[i]=temp[i] ;

      }     

      

           saveConfig();

           loadConfig();

 

            // redirect to the home page

            buf.emit_p(PSTR(

                "HTTP/1.0 302 found\r\n"

                "Location: /\r\n"

                "\r\n"));

            return;

        

    }

    // else show a configuration form

    buf.emit_p(PSTR("$F\r\n"

        "<h3>naNode API settings</h3>"

        "<form>"

          "<p>"      

            "Domain   <input type=text name=domain value='$S' size=32><br>"

            "API   <input type=text name=api value='$S' size=64><br>"

          "</p>"

          "<input type=submit value=Set> <input type=button value=Back onclick='history.go(-1)'>"

        "</form>"),okHeader,

        config.domain, config.api );

}

 

 

 

void loop(){

  

 

    word len = ether.packetReceive();

    word pos = ether.packetLoop(len);

    // check if valid tcp data is received

    if (pos) {

        bfill = ether.tcpOffset();

        char* data = (char *) Ethernet::buffer + pos;

#if SERIAL

       // Serial.println(data);

#endif

        // receive buf hasn't been clobbered by reply yet

        if (strncmp("GET / ", data, 6) == 0)

            homePage(bfill);

        else if (strncmp("GET /c", data, 6) == 0)

            configPage(data, bfill);

        else if (strncmp("GET /a", data, 6) == 0)

            apiPage(data, bfill);

 

        else

            bfill.emit_p(PSTR(

                "HTTP/1.0 401 Unauthorized\r\n"

                "Content-Type: text/html\r\n"

                "\r\n"

                "<h1>401 Unauthorized</h1>"));  

        ether.httpServerReply(bfill.position()); // send web page data

    }

 

}

TrystanLea's picture

Re: naNode web configuration sketch

 Awesome, thanks mharizanov, looks great

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.