Problem Trying to Reset Webserver Form Values

Hi. I am trying to make a sketch to monitor and manipulate my garage door. I am reusing a common webserver sketch as the basis of the project. I have most of the sketch done but there is one area that has stumped me to this point.

Depending on the placement of the garage door, the webserver can have two buttons, "Open Door" and "Close Door". When I press "Open Door" the URL in the web browser turns to "http://192.168.0.31/?b=1", when I click the "Close Door" button, the URL in the web browser turns to "http://192.168.0.31/?b=2". I want it to send a half second pulse to the garage door opener via a relay module.

The webserver is set to refresh itself every 5 seconds. After I click the "Open Door" button, the relay pulses every 5 seconds. I only want it to pulse once. I have tried several methods of "resetting" the form (see the "reset form FAILS!" section of the sketch in the next post). Is there a way to reset the form or clear the value of "b" in the URL? Is there a way to change the URL from "http://192.168.0.31/?b=1" to "http://192.168.0.31/" on each 5 second reset?

Thanks!

:D Oops, I missed the "9500 character limit". I will post the sketch in smaller parts.

Part 1 of 3

#include <Time.h>
#include <MemoryFree.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

// ethernet configuration
byte mac[] = { 
  0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
byte ip[] = { 
  192, 168, 0, 31 };  // ip in lan
byte gateway[] = { 
  192, 168, 0, 1 };  // internet access via router
byte subnet[] = { 
  255, 255, 255, 0 };  //subnet mask
EthernetServer server(80);  // port 80 is default for HTTP

// constants
const int AutoDownEnablePin = 6;  // enable autodown switch
const int DoorClosedPin = 7;  // door open switch
const int DoorOpenPin = 8;  // door closed switch
const int OpenCloseRelayPin1 =  9;
const int OpenCloseRelayPin2 =  5;
//const int LED = 9;  // led is connected to digital pin 9
const int timeZone = -5;  // Central Standard Time (USA)

// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov

// variables
boolean DoorOpenState;
boolean DoorClosedState;
int DoorPosition;
boolean RelayEnable1;
String TimeString;
long TempTime;
int SecondsOpen = 0;
int MinutesOpen;
boolean AutoDownSwitch;
boolean AutoDownEnable;
int AutoDownMinutes;
char c = 0;  // received data
char command[2] = "\0";  // command

EthernetUDP Udp;
unsigned int localPort = 7777;  // local port to listen for UDP packets

void setup()
{
  // initialize serial communication:
  Serial.begin(9600);

  // initialize IOs
  pinMode(AutoDownEnablePin, INPUT_PULLUP);
  pinMode(DoorOpenPin, INPUT_PULLUP);
  pinMode(DoorClosedPin, INPUT_PULLUP);
  pinMode(OpenCloseRelayPin1, OUTPUT);
  //pinMode(OpenCloseRelayPin2, OUTPUT);
  //pinMode(LED, OUTPUT);

  // initialize webserver
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  // initialize udp for time sync
  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
}

time_t prevDisplay = 0; // when the digital clock was displayed

void loop()
{
  updatetime();
  switchstatus();
  webserver();
  
  goto skipit;
  
  Serial.print(F("freeMemory()="));
  Serial.println(freeMemory());
  
  skipit:
  ;
}

void switchstatus()
{
  // read the state of the pushbutton value:
  DoorOpenState = digitalRead(DoorOpenPin);
  DoorClosedState = digitalRead(DoorClosedPin);

  // calculate door status
  if (DoorClosedState == 1 && DoorOpenState == 0){
    DoorPosition = 0;
  }  // door is open
  if (DoorClosedState == 0  && DoorOpenState == 0){
    DoorPosition = 1;
  }  // door is in middle position
  if (DoorClosedState == 0  && DoorOpenState == 1){
    DoorPosition = 2;
  }  // door is open
  if (DoorClosedState == 1  && DoorOpenState == 1){
    DoorPosition = 3;
  }  // ERROR unknown state

  goto skipit;

  //Print the results
  Serial.print(F("Closed="));
  Serial.print(DoorClosedState);
  Serial.print(F(",Open="));
  Serial.print(DoorOpenState);
  Serial.print(F(",Door="));
  Serial.print(DoorPosition);
  Serial.println();

  skipit:
  ;
}

Part 2 of 3

void webserver()
{
  EthernetClient client = server.available();
  // detect if current is the first line
  boolean current_line_is_first = true;

  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println();
          
          // auto reload webpage every 5 second
          client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=>"));

          // background
          //client.println(F("<body background=\"http://img256.imageshack.us/img256/5867/52577012.jpg\"</body>");
            
          //webpage background color
          client.println(F("<body bgcolor=silver>"));

          // webpage title
          client.println(F("<title>Garage Monitor</title>"));

          // webpage heading
          client.println(F("<center><font face='Verdana' color='black' size='8'>Garage Monitor</font></center>"));
          client.println(F("
"));  // line break
          client.println(F("
"));
          client.println(F("<hr>"));  // horizontal line
          client.println(F("
"));
          client.println(F("
"));

          // reset form FAILS!
          //client.println(F("<script>"));
          //client.println(F("<document.form.reset()>"));
          //client.println(F("</script>"));
          //client.println("<body onLoad=javascript:document.forms[0].reset()>");
          //client.println(F("<input type=reset value=Reset Form>"));
          //client.println(F("<form  method=get name=form autocomplete=off>"));
          //client.println(F("<body onload=document.form.reset();>"));
          //client.println(F("<form autocomplete=off>"));
          //client.println(F("<a href=javascript:document.form.reset();>reset</a>"));
          //client.println(F("<script>document.form.reset()</script>"));
          //client.println(F("<script type=text/javascript>"));
          //client.println(F("document.getElementById('b').value ='';"));
          //client.println(F("</script>"));
          
          // button functions
          client.println(F("<form  method=get name=form>"));
          if (DoorPosition == 0){
            //The door is closed
            //client.println(F("<hr><center><a href=http://www.URL.com>URL Link Text</a>
");
            //"<button disabled name=b (to disable a button)
            //font-size:36;color:grey (changes button font color)
            client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightpink>Open Door</button></center>"));
          }
          if (DoorPosition == 1){
            //The door is open
            client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightpink>Open Door</button></center>"));
            client.println(F("
"));
            client.println(F("
"));
            client.println(F("<center><button name=b value=2 type=submit style=height:300px;width:600px;font-size:36;background-color:lightgreen>Close Door</button></center>"));
          }
          if (DoorPosition == 2){
            //The door is open
            client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightgreen>Close Door</button></center>"));
          }
          client.println(F("</form>
"));
          client.println(F("
"));
          client.println(F("<hr>"));

          // Status Panel
          client.println(F("
"));
          client.println(F("<center><font face='Verdana' color='black' size='8'>Status Panel</font></center>"));
          client.println(F("
"));
          client.println(F("<center><font face='Verdana' color='black' size='6'>"));

          // display time
          client.println(String(TimeString));
          client.println(F("
"));

          // display free memory
          client.println("Free Memory: " + String(freeMemory()));
          client.println(F("
"));
          client.println(F("
"));

          // door position
          switch (DoorPosition){
          case 0:
            SecondsOpen = 0;
            MinutesOpen = 0;
            AutoDownEnable = 0;
            client.println(F("Door Position: Closed"));
            client.println(F("
"));
            break;
          case 1:
            client.println(F("Door Position: Middle"));
            client.println(F("
"));
            break;
          case 2:
            if (SecondsOpen == 0){
              TempTime = now();
            }
            MinutesOpen = SecondsOpen / 60;
            client.println("Door Position: Open (" + String(MinutesOpen) + " Minutes)");
            client.println(F("
"));
            delay(1000);
            SecondsOpen = now() - TempTime;
            break;
          case 3:
            client.println(F("Door Position: ERROR!"));
            client.println(F("
"));
            break;
          }

          // door switch status
          if (digitalRead(DoorClosedPin) == HIGH){
            client.println(F("Door Closed Switch: High"));
          }
          else{
            client.println(F("Door Closed Switch: Low"));
          }
          client.println(F("
"));
          if (digitalRead(DoorOpenPin) == HIGH){
            client.println(F("Door Open Switch: High"));
          }
          else{
            client.println(F("Door Open Switch: Low"));
          }
          client.println(F("
"));
          client.println(F("
"));

          // autodown
          AutoDownMinutes = 15;  // 15 minute auto down
          client.println("AutoDown Minutes: " + String(AutoDownMinutes));
          client.println(F("
"));

          AutoDownSwitch = digitalRead(AutoDownEnablePin);
          if (AutoDownSwitch == HIGH){
            client.println(F("AutoDown Enabled: True"));
          }
          else{
            client.println(F("AutoDown Enabled: False"));
          }
          client.println(F("
"));

          if ((DoorOpenState == 1 && AutoDownSwitch == HIGH && MinutesOpen >= AutoDownMinutes) || (AutoDownEnable == 1)){
            AutoDownEnable = 1;
            client.println(F("Close Door: True"));
          }
          else{
            AutoDownEnable = 0;
            client.println(F("Close Door: False"));
          }
          client.println(F("
"));
          client.println(F("
"));
          client.println(F("<hr>"));

          client.println(F("</font></center>"));

          break;
        }
        
        // read form value of "b"
        if (c == '\n') {
          // we're starting a new line
          current_line_is_first = false;
          current_line_is_blank = true;
        } 
        else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
        // get the first http request
        if (current_line_is_first && c == '=') {
          for (int i = 0; i < 1; i++) {
            c = client.read();
            command[i] = c;
          }
          // Relay control
          if (!strcmp(command, "1")){ // && RelayEnable1 == 1) {
            // open door
            digitalWrite(OpenCloseRelayPin1, HIGH); //LOW for relay module
            delay(500);
            digitalWrite(OpenCloseRelayPin1, LOW); //HIGH for relay module
            //RelayEnable1 = 0;
          }
          else if (!strcmp(command, "2")) {
            //close door
          }
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

Part 3 of 3

//***********************************NTP***********************************

void printDigits(int digits){
  // utility for digital clock display: prints preceding colon and leading 0
  if(digits < 10)
    TimeString = TimeString + "0";
    TimeString = TimeString + digits;
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()

{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println(F("No NTP Response :-("));
  return 0; // return 0 if unable to get the time
}

void updatetime()
{  
  if (timeStatus() != timeNotSet){
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();  
    }
  }
}

void digitalClockDisplay(){
  // digital clock display of the time
  TimeString = "";

  printDigits(month());
  TimeString = TimeString + "/";
  printDigits(day());
  TimeString = TimeString + "/";
  printDigits(year());
  TimeString = TimeString + " - ";
  printDigits(hour());
  TimeString = TimeString + ":";
  printDigits(minute());
  TimeString = TimeString + ":";
  printDigits(second());
  
  goto skipit;
  
  Serial.print(TimeString);
  Serial.println();
  
  skipit:
  ;
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address){
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

Is there a way to change the URL from "http://192.168.0.31/?b=1" to "http://192.168.0.31/" on each 5 second reset?

Put a clickable link for "http://192.168.0.31/?b=1" in the "http://192.168.0.31/" refreshing page.

Thanks for the quick reply zoomkat!! I just tried clicking “http://192.168.0.31/?b=1” in your post and it “pulses” on every 5 second refresh. I also tried…

client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=192.168.0.31>"));

and

client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=http://192.168.0.31/>"));

But it didn’t change the behavior. I’m not sure I am doing what you suggested.

Web page with clickable links. Put a meta refresh line if needed.

//zoomkat 3-17-12
//simple button GET server code to control servo and arduino pin 5
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html 
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields

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

//#include <Servo.h> 
//Servo myservo;  // create servo object to control a servo 

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 
  192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 
  192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 
  255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString; 

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  pinMode(6, OUTPUT); //pin selected to control
  pinMode(7, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("server LED test 1.0"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Arduino GET test page</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>Zoomkat's simple Arduino button</H1>");

          // DIY buttons
          client.println("<a href=\"/?on1\"\">ON</a>"); 
          client.println("<a href=\"/?off1\"\">OFF</a>
"); 

          // mousedown buttons
          client.println("
<input type=\"button\" value=\"ON\" onmousedown=\"location.href ('/?on2');\"/>"); 
          client.println("<input type=\"button\" value=\"OFF\" onmousedown=\"location.href ('/?off2');\"/>");        

          // mousedown radio buttons
          client.println("

<input type=\"radio\" value=\"ON\" onmousedown=\"location.href ('/?on3');\"\">ON</>"); 
          client.println("<input type=\"radio\" value=\"OFF\" onmousedown=\"location.href ('/?off3');\"\">OFF</>");        

          client.println("</BODY>");
          client.println("</HTML>");

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on1") >0) {
            digitalWrite(5, HIGH);
            Serial.println("Led on1");
          }
          if(readString.indexOf("off1") >0) {
            digitalWrite(5, LOW);
            Serial.println("Led off1");
          }

          if(readString.indexOf("on2") >0) {
            digitalWrite(6, HIGH);
            Serial.println("Led on2");
          }
          if(readString.indexOf("off2") >0) {
            digitalWrite(6, LOW);
            Serial.println("Led off2");
          }

          if(readString.indexOf("on3") >0) {
            digitalWrite(7, HIGH);
            Serial.println("Led on3");
          }
          if(readString.indexOf("off3") >0) {
            digitalWrite(7, LOW);
            Serial.println("Led off3");
          }
          //clearing string for next read
          readString="";          
        }
      }
    }
  }
}

Crap…

I tried the meta refresh as one of the first attempts to fix it. Unfortunately Mr. Syntax kicked me in the under carriage. I forgot a “;” before “URL”. I changed…

client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=http://192.168.0.31/>"));

to

client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5;URL=http://192.168.0.31/>"));

Now it’s working pretty well. Thanks zoomkat!!