• Skip to main content
  • Skip to primary sidebar

RNTLab.com

The Ultimate Shortcut to Learn Electronics and Programming with Open Source Hardware and Software

  • Courses
  • Forum
    • Forum
    • Ask Question
  • Shop
  • Account
  • Blog
  • Login

Sample web page

Q&A Forum › Category: ESP32 › Sample web page
0 Vote Up Vote Down
Lance Benson asked 7 years ago

I received my first ESP32s on Tuesday; started working through Rui’s tutorial, and now, Friday, I’d like to show how I’ve progressed in moving a PICAXE BASIC web application to the ESP32. (NB: I programmed a lot in C, but that was 30+ years ago.)

This was for control of a water system with two saline wells, a holding tank, a reverse osmosis module to remove salt, a drinkable holding tank, and various pumps and sensors.

The base HTML code is in the form of a template stored in a 24LC64 eeprom (4144 bytes written). It contains tags for variables to be inserted in the code, in the form of ~##, e.g., ~01 through ~99. When a client request comes in, the program scans through the html code and replaces ~## with the appropriate value (something read from a sensor). In this program, those are just fixed values–I haven’t connected to the sensors and fed in their values. I also haven’t implemented the inputs from the web page.water system monitor web page

Whenever the program connects to the router, it uses sntp to get the current time (in Nova Scotia). That is displayed on the web page.

Issues: usually have to press the “Enable” button to get the eeprom to be read properly.

Many thanks to Rui for the tutorial, which gave me just what I needed to port this web server to the ESP32.

// webwater controls a water delivery system with 2 saline wells,
//   2 saline holding tanks, 2 reverse osmosis filters, a drinkable holding tank,
//   and various sensors and pumps

// Load Wi-Fi library
#include 
#include 
#include 
#include 
#include "apps/sntp/sntp.h"

// Replace with your network credentials
const char* ssid     = "mySSID;
const char* password = "myPW";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

static void obtain_time(void);
static void initialize_sntp(void);

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
char templt[5000]; // array to hold web page template
time_t now;
struct tm timeinfo;
char strftime_buf[64];
int iVarval[100];

void setup() {
  Serial.begin(115200);
  Wire.begin();
  delay(1000);
  eepromGet(); // read web page template from eeprom
  delay(1000);
  // Initialize the output variables as outputs
  /*
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);
  */
  
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);
  setup_time();
  delay(1000);
  server.begin();
  // set initial variable values--liters pumpte
  iVarval[3]=27;iVarval[4]=31;iVarval[5]=62;iVarval[6]=407;iVarval[7]=27;iVarval[8]=57;iVarval[9]=388;iVarval[10]=25;iVarval[11]=48;iVarval[12]=320;
  iVarval[13]=6;iVarval[14]=14;iVarval[15]=87;
  iVarval[16]=117;iVarval[17]=144;iVarval[18]=111;iVarval[19]=108; // salinity
  iVarval[20]=999;iVarval[21]=998;iVarval[22]=999;iVarval[23]=999; // water level: 999="OK", 998="Low"
  iVarval[24]=997;iVarval[25]=996;iVarval[26]=997;iVarval[27]=997;iVarval[28]=997; // pump: 997--off="blue", 996--on="green"
}

void loop(){
  int i, k, iLimit, iVarndx, iVal;
  char ch;
  iLimit = 4144; // max characters in template
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String 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
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
              Serial.printf("Header: %s",header);
            // checking if header is valid
            // dXNlcjpwYXNz = 'user:pass' (user:pass) base64 encode
            // Finding the right credential string, then loads web page
//            if(header.indexOf("bGl6Ynk6bTNkd2F5NDIx") >= 0) {
            if(true) {
              // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
              // and a content-type so the client knows what's coming, then a blank line:
              client.println("HTTP/1.1 200 OK");
              client.println("Content-type:text/html");
              client.println("Connection: close");
              client.println();

/*
              // turns the GPIOs on and off
              if (header.indexOf("GET /26/on") >= 0) {
                Serial.println("GPIO 26 on");
                output26State = "on";
                digitalWrite(output26, HIGH);
              } else if (header.indexOf("GET /26/off") >= 0) {
                Serial.println("GPIO 26 off");
                output26State = "off";
                digitalWrite(output26, LOW);
              } else if (header.indexOf("GET /27/on") >= 0) {
                Serial.println("GPIO 27 on");
                output27State = "on";
                digitalWrite(output27, HIGH);
              } else if (header.indexOf("GET /27/off") >= 0) {
                Serial.println("GPIO 27 off");
                output27State = "off";
                digitalWrite(output27, LOW);
              }
 */
              
              // Display the HTML web page
              client.println("");
              i = 0; 
              ch = templt[i++]; 
              do {
                if (ch >= ' ' && ch <= '~') { // is printable
                  if (ch == '~') {            // token needing replacement
                    ch = templt[i++];
                    iVarndx = ((int)ch-(int)'0') * 10 + (int)templt[i++]-(int)'0';
//                    Serial.printf("%d \n",iVarndx); 
                    switch(iVarndx) {
                      case 1: // date
                        time(&now);
                        localtime_r(&now, &timeinfo);
                        strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
                        client.printf("%s", strftime_buf);
                        break;
                      case 2: // time--included in "date" above
                        break;
                      case 29: 
                      case 30: 
                      case 31: // chart--not implemented
                        delay(1); // dummy command
                        break;
                      default:
                        iVal =  iVarval[iVarndx];
                        if (iVal == 999) {
                          client.printf("OK");
                        } else if (iVal == 998) {
                          client.printf("Low");
                        } else if (iVal == 997) {
                          client.printf("\"yellow\"");
                        } else if (iVal == 996) {
                          client.printf("\"green\"");
                        } else if (iVal == -1) {  // do nothing
                        } else {
                          client.printf("%d",iVal); // print the value
                        }
                    }
                  } else {
                    client.printf("%c",ch); 
                    Serial.printf("%c",ch); 
                  }
                }
                ch = templt[i++]; 
              } while (ch != 0xFE && i < iLimit);

              // The HTTP response ends with another blank line
              client.println();
              // Break out of the while loop
              break;
            }
            // Wrong user or password, so HTTP request fails...   
            else {            
              client.println("HTTP/1.1 401 Unauthorized");
              client.println("WWW-Authenticate: Basic realm=\"Secure\"");
              client.println("Content-Type: text/html");
              client.println();
              client.println("Authentication failed");
            }   
          } 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
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

void eepromGet(){
int iCount, iCh, i;
char ch, *c, *s;
// char templt[5000]; // array to hold web page template
  iCount = 0; iCh = 0;
  Wire.beginTransmission(0x50);
  Wire.write(0);  // start at address 0 MSB
  Wire.write(0);  // start at address 0 LSB
  Serial.println(); 
  do {
    int err = Wire.requestFrom(0x50,128,false); // request # bytes ("true" releases bus)
    if(err != 128){
//      Serial.printf(" requestFrom Failed, expected 128 bytes, received =%d\nError %d (%s)\n",err,Wire.lastError()),Wire.getErrorText(Wire.lastError)));
      Serial.printf(" requestFrom Failed, expected 128 bytes, received =%d\n",err);
      }
    else { // display it
      while(Wire.available()){
 //       Serial.printf("%c",Wire.read());
          ch = Wire.read();
          templt[iCh++] = ch;
         }
//       Serial.printf("%d ",iCount);
//     Serial.println(); 
    }
    iCount+= 128;
  } while (iCount < 4144 && ch != 0xFE);
  templt[iCh] = 0; // terminate string
  Wire.requestFrom(0x50,1,true); // request # bytes ("true" releases bus)
  s = &templt[0]; // get address of string
  c = strstr(s, "content=");
  if(c != NULL) {
    i = c - s + 9; // index into template
    templt[i++]='9';
    templt[i++]='9';
    templt[i++]='9';
    templt[i++]='"'; // replace refresh time of "15" with "999"
  }
  i = 0; ch = templt[i++]; do { Serial.printf("%c",ch); ch = templt[i++]; } while (ch != 0xFE && i < iCh);
  Wire.endTransmission(true);
} 

static void setup_time(void)
{
//    char strftime_buf[64];

    obtain_time();
    // update 'now' variable with current time
    time(&now);
    // Set timezone to Atlantic Time and print local time
    setenv("TZ", "AST4ADT,M3.2.0/2,M11.1.0", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    Serial.printf("The current date/time in Halifax is: %s", strftime_buf);
}

static void obtain_time(void)
{
//    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
    initialize_sntp();

    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 10;
    while(timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        time(&now);
        localtime_r(&now, &timeinfo);
    }
}

static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_init();
}

EDIT: Figured out how I had enabled the chart, so added that. Also, I was getting “Brownout” resets; adding a 3300uF capacitor across the power runs on my breadboard fixed that.

5 Answers
0 Vote Up Vote Down
Lance Benson answered 7 years ago

Here is the html template code which is stored in the eeprom (the chart in the code is not implemented):
… hmmm. I can’t figure out how to insert the html code literally without its being interpreted.

0 Vote Up Vote Down
Rui Santos Staff answered 7 years ago

Hi Lance,

Thanks for sharing your progress and I’m glad you were able to modify/make your project work (I’ll be posting a new tutorial this week on the RNT blog about requesting the current time from an NTP server).

Tip: If your HTML page starts to get too long and you find it difficult to write/edit HTML, you might consider following the approach described in this project: ESP32 Weather Station.

Basically in that project, we store all the HTML formatting in a MicroSD card and when a client requests a web page we load it through the microSD card.

P.S. To avoid problems inserting code, you can post it to https://pastebin.com/ and simply post a link on this Forum.

0 Vote Up Vote Down
Lance Benson answered 7 years ago

Thanks. I’m looking at the ESP32 Weather Station blog to see about hooking up a microSD card to my 32s module. It apparently has pins defined (or suggested) for SD–GPIO6-11, marked in green in the diagram. I assume the pin definition is in sd.h. Where is that located?

ESP32 NodeMCU 32s pinout

0 Vote Up Vote Down
Lance Benson answered 7 years ago

To Answer my own question, the SD pin definitions are not defined in SD.h, but are apparently defined for the 32s module. They are the same as in the Weather Station SD wiring. The green pins in the image above are for the flash (as marked)–trying to put an SD card on them causes the module to fail to boot.

Correctly wired, SD_Test.ino worked successfully. The wiring for the NodeMCU-32S SD is shown at https://github.com/espressif/arduino-esp32/tree/master/libraries/SD: SD card wiring for NodeMCU-32s module

0 Vote Up Vote Down
Rui Santos Staff answered 7 years ago

Thanks for sharing your results and schematics Lance! Let me know if you need anything else.

Regards,
Rui

Primary Sidebar

Login to Ask or Answer Questions

This Forum is private and it’s only available for members enrolled in our Courses.

Login »

Latest Course Updates

  • [New Edition] Build ESP32-CAM Projects eBook – 2nd Edition April 16, 2025
  • [eBook Updated] Learn ESP32 with Arduino IDE eBook – Version 3.2 April 16, 2025

You must be logged in to view this content.

Contact Support - Refunds - Privacy - Terms - MakerAdvisor.com - Member Login

Copyright © 2013-2025 · RandomNerdTutorials.com · All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.