Using HTML Form data in projects on Wi-Fi Uno Rev2

I’m trying to make a Wi-Fi controlled thermostat using a Wi-Fi Uno Rev2, a relay and a temperature sensor. The wiring is pretty basic and so far works fine, but I’m having issues coding the web interface. Specifically, I am trying to use a form to set up programs to change the thermostat’s set temperature, at certain times of day, on certain days.

My base code is adapted from an example sketch included with the WifiNina library, SimpleWebServerWifi, along with some code I cut and pasted from example sketch TimeNTP_ESP8266WiFi to retrieve time, plus a lot of container variables and general code that I added myself.

In particular, the code from SimpleWebServerWifi uses a string named currentLine to hold the URL, and then does things like

if (currentLine.endsWith(“GET /L”)) {
digitalWrite(9, LOW); // GET /L turns the LED off
}

…I’ve successfully adapted this code to do whatever I define by clicking links, but forms seem to be a whole other beast. I’m using form method = get, so that whatever the user selects will come up in the URL, and then trying to scrape it with, for example, this

bagofholding = currentLine.indexOf(‘S’, 6);
if ((currentLine.indexOf(‘u’, 6)-bagofholding) ==1) {
Sunday = 1;}

(bagofholding is a generic integer container that I reuse when I just want to hold a value briefly.) The form should return Su (among other things) in the URL if the Sunday checkbox was checked, and so what I’m trying to do here is read for those two letters consecutively and mark the variable “Sunday” as 1 if they are there.

Unfortunately, Serial monitor seems to be unhappy trying to debug my code while everything else is going - it crashes on me after a little while, making it hard to go back and see what values it’s spitting out where, but I set up a makeshift table that shows up on the web page that should show the values of the program container variables (Sunday-Saturday, slots 1-4 for each, plus a set designated with a T for temperature) - but these remain at 0, telling me that no value is being committed to them.

My best guess is that I’m either not properly capturing the full URL when I submit the form or that I’m not properly searching the resulting string for my data; in either case I could desperately use some help figuring out what to do.

I’ve attached my sketch - my apologies in advance that it’s a little bit messy, and my thanks in advance for any help that anyone can offer.

Wifi_Uno_Thermostat3.ino (20.9 KB)

#include <SPI.h>
#include <WiFiNINA.h>

//containers for day, time and temperature programs
int c1s1, c1s2, c2s1, c2s2;
int bagofholding; //for momentarily holding data
char boxofcarrying; //for momentarily holding more data
byte slotNumber; //tracks which slot to stash the data in
int debuggery; //an int for holding data for debug
byte Checkbox1, Checkbox2;
char t1, t2; //variables for catching  the temperature digits from the form
int temp;

// Please enter your sensitive data in the Secret tab/arduino_secrets.h
#include "arduino_secrets.h"
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)

String currentLine = ""; //String to hold incoming data from the client, declared globally for use in subroutines

// Wifi Components
int status = WL_IDLE_STATUS;
WiFiServer server(80);

void setup() {
  String fv = WiFi.firmwareVersion();
  
  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
      status = WiFi.begin(ssid, pass);
        delay(10000);
  }
  server.begin();                           // start the web server on port 80

//Serial.begin(115200);
}

void loop() {

  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
  // Serial.println("new client");           // print a message out the serial port
    currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
   //     Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

            if (currentLine.length() == 0) { 
            
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            // the content of the HTTP response follows the header:
            client.print("
To define a program, fill out the form below:
What days should this program run?
");
            client.print("<form method=\"get\">  <input type=\"checkbox\" name=\"Aa\" value=\"1\"> Checkbox 1
<input type=\"checkbox\" name=\"Bb\" value=\"1\"> Checkbox 2


What temperature should be set?
<input type=\"number\" name=\"Cc\" min=\"40\" max=\"90\" step=\"1\" value=\"60\">

Pick a memory slot for the defined program:
<input type=\"radio\" name=\"Slot\" value=\"1\" checked> 1; <input type=\"radio\" name=\"Slot\" value=\"2\"> 2
<input type=\"submit\" value=\"Submit\"> <input type=\"reset\"></form> ");
            client.print("

Recorded programs:
______ Sunday Monday Tuesday Wednesday Thursday Friday Saturday
");
            //a makeshift table to display what values have been assigned to what memory slots
            client.print("Prog 1: "); client.print(c1s1); client.print(" "); client.print(c1s2);
            client.print("Prog 2: "); client.print(c2s1); client.print(" "); client.print(c2s2);
                        
                        // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        scrapeUrl(); //Go to subroutine to process feedback from links / form
        setprogs(); //Go to subroutine to apply form data to memory slots  

      }    
    }
    // close the connection:
    client.stop();
  }
}

void scrapeUrl(){

        Checkbox1 = 0;
        Checkbox2 = 0;

         //Checking to see if Aa exist in sequence      
         bagofholding = currentLine.indexOf('A');
          if ((currentLine.indexOf('a')-bagofholding) ==1) {
          Checkbox1 = 1;}

          //Checking to see if Bb exist in sequence 
          bagofholding = currentLine.indexOf('B');
          if ((currentLine.indexOf('b')-bagofholding) ==1) {
          Checkbox2 = 1;}
          
          //Read the number at the end of the URL
          bagofholding = currentLine.length();
          boxofcarrying = currentLine.charAt(bagofholding);
          slotNumber = (boxofcarrying - '0');

          //Get the temperature entry
          //Looking for Cc in sequence and reading the 2nd and 3rd characters after the 'c'
          bagofholding = currentLine.indexOf('C');
          bagofholding = currentLine.indexOf('c', bagofholding);
          t1 = currentLine.charAt(bagofholding +2);
          t2 = currentLine.charAt(bagofholding +3);
          temp = (((t1-'0')*10)+(t2-'0'));
}


void setprogs(){
 // Serial.println("Processing subroutine 'setprogs'");
  if (slotNumber ==1){
            if (Checkbox1 == 1) {
              c1s1 = temp;
            }
            if (Checkbox2 == 1) {
              c2s1 = temp;
            }
   }
  if (slotNumber ==2){
            if (Checkbox1 == 1) {
              c1s2 = temp;
            }
            if (Checkbox2 == 1) {
              c2s2 = temp;
            }

   }
            //Clear the days variables
        Checkbox1 = 0;
        Checkbox2 = 0;
        slotNumber = 0;
}

Unfortunately, Serial monitor seems to be unhappy trying to debug my code

Rubbish. The Serial Monitor application has no clue what the bytes you are sending it are for.

I've clipped unrelated code chunks below because the original is too long to post here

Apparently, you are unable to read the stickies at the top of the forum, which explain how to attach your complete code when you've developed too much code without debugging it piece by piece.

Until you pot ALL of your code, I'm not going to look at your random snippage.

I will note that using global variables for everything is an abomination. Use local variables as needed, and give each one a meaningful name in the context where it is used.

Using Strings on most Arduinos is a bad idea.

Nowhere in the snippets do you print currentLine, so you are guessing what you are parsing. Never a good idea.

PaulS:
Rubbish. The Serial Monitor application has no clue what the bytes you are sending it are for.

That’s fair enough, but the fact is that for whatever reason Serial Monitor (and the IDE in general) are crashing on me after a minute or two of reading the serial output from the WiFi Uno. Maybe it’s a problem with my computer’s environment, hell I don’t know, but the fact is it’s crashing on me.

PaulS:
Apparently, you are unable to read the stickies at the top of the forum, which explain how to attach your complete code when you’ve developed too much code without debugging it piece by piece.

I looked at the post “Read this before posting a programming question”. I saw the part about tagging the code with [ code ], but when I tried to post it, it gave me errors about being too many characters long (over 9000 characters). I checked back through the stickies to see if I missed something. If you can point me in the right direction, that would be helpful.

PaulS:
Until you pot ALL of your code, I’m not going to look at your random snippage.

I did attach my full sketch on the original post, but I don’t know how to make it display here.

I did attach my full sketch on the original post

I missed that.

  while (status != WL_CONNECTED) {
  //  Serial.print("Attempting to connect to ");
  // Serial.println(ssid);
      status = WiFi.begin(ssid, pass);
        delay(10000);
        processThermoState(); //Check whether the thermostat should be on or off and switch accordingly
        }

Your indentation leaves a lot to be desired. Tools + Auto Format would make it look like you knew what you were doing.

What is the point of processing the thermo state when you are not connected?

Do that ONCE, AFTER you are connected.

.
");}else{

Put ONE statement per line. Put EVERY { on a line BY ITSELF. Put EVERY } on a line BY ITSELF.

I still say that without printing currentLine, you have no idea what you are parsing, and that you are parsing by guesswork. Print currentLine, so you KNOW what you are parsing, and what assumptions you have made that are false.

PaulS:
I still say that without printing currentLine, you have no idea what you are parsing, and that you are parsing by guesswork. Print currentLine, so you KNOW what you are parsing, and what assumptions you have made that are false.

That was a good idea. Turns out there's a lot more going into that string than I realized. Will attempt to see what I can work out of it after I get some sleep and update if more help is needed. Thank you for your time.

Turns out there's a lot more going into that string than I realized.

That, of course, was what I suspected. Good luck with the project. Now that you know what you are dealing with, parsing it should be pretty simple.