Default Jaycar code having issues

Hi!

A couple days ago I bought an arduino uno board with a builtin ESP8266 from jaycar electronics: https://www.jaycar.com.au/uno-with-wi-fi/p/XC4411

However, under the "Downloads" tab you can get a manual describing how to set the DIP switches, as well as some software to test out the board. The code for the ESP8266 is what's throwing me. I'm quite experienced with arduino code (As my earlier posts will show), but this code keeps throwing a compile error. You can download the code yourself from the jaycar website, or just copy it from here

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#define SERIAL_BAUD 115200 //make sure this is the same in arduino.ino

ESP8266WebServer server(80);

String serialData = "";

//this is our HTML website that we send to the user, much easier to use SPIFFS in future.
const String html_page = "<!DOCTYPE html>"
												 "<html>"
												 "  <head>"
												 "    <meta name='viewport' content='width=device-width, initial-scale=1.0' />"
												 "  </head>"
												 "  <body>"
												 "    <a href='/ledon'>turn LED on</a>"
												 "    <a href='/ledoff'>turn LED off</a>"
												 "    <h1>Latest data from arduino:</h1>"
												 "    <pre id='reading'></pre>"
												 "    <script>"
												 "      (function() {"
												 "        /* get new data every second*/"
												 "        setInterval(function() {"
												 "          fetch('/reading')"
												 "					.then(response => { return response.text();})"
												 "					.then(text => {"
												 "            document.getElementById('reading').textContent = text;"
												 "          });"
												 "        }, 100);"
												 "      })();"
												 "    </script>"
												 "  </body>"
												 "</html>";

const IPAddress serverIPAddress(10, 0, 0, 7);

void setup() {
	Serial.begin(SERIAL_BAUD);

	//here we set up as a hot spot, called XC4411 dual board
	WiFi.softAPConfig(serverIPAddress, serverIPAddress, IPAddress(255, 255, 255, 0));
	WiFi.softAP("XC4411 Dual Board example code");

	//here we set server paramters, the main page is the html_page from above
	server.on("/", []() { //send html code, from above
		server.send(200, "text/html", html_page);
	});

	//reading is just a copy of the serial Data
	server.on("/reading", []() { //send raw serial data
		Serial.println();
		Serial.println(serialData);
		server.send(200, "text/plain", serialData);
	});

	server.on("/ledon", []() {
		Serial.println("[LEDON]"); //send serial data to arduino
		server.send(200, "text/plain", "ok");
	});
	server.on("/ledoff", []() {
		Serial.println("[LEDOFF]"); //send serial data to arduino
		server.send(200, "text/plain", "ok");
	});
	server.on("/ledtoggle", []() {
		Serial.println("[LEDTOGGLE]"); //send serial data to arduino
		server.send(200, "text/plain", "ok");
	});

	server.onNotFound(handleNotFound);
	server.begin();
}

void loop() {
	while (Serial.available()) { char x = Serial.read(); if (x == '\r') { continue; } serialData += x; }
	server.handleClient();
}

void handleNotFound() {
	String message = "File Not Found\n\n";
	message += "URI: ";
	message += server.uri();
	message += "\nMethod: ";
	message += (server.method() == HTTP_GET) ? "GET" : "POST";
	message += "\nArguments: ";
	message += server.args();
	message += "\n";
  
	for (uint8_t i = 0; i < server.args(); i++) {
		message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
	}
 
	server.send(404, "text/plain", message);
}

Normally I would just test out the example code to see it work, delete it, then start making my own code (I've worked with the ESP8266 before, so it's not that hard). HOWEVER, I cannot for the life of me find out why the compiler is throwing an error. The error shows:

Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
In file included from C:\Users\aj200\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h:30:0,

from C:\Users\aj200\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\ESP8266WebServer\src/ESP8266WebServer.h:235,

from C:\Users\aj200\Downloads\XC4411-softwareMain\dualcode\esp\esp.ino:3:

C:\Users\aj200\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\ESP8266WebServer\src/detail/RequestHandlersImpl.h:67:28: error: expected ')' before '&' token

StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header)

^

esp:95:1: error: expected '}' at end of input

}

^

esp:95:1: error: expected unqualified-id at end of input

esp:95:1: error: expected '}' at end of input

exit status 1
expected '}' at end of input

I've gone through and checked to make sure the code doesn't have any random unclosed brackets, but nothing shows up. Am I missing something obvious here? I usually am missing the obvious.

Any help would be appreciated.

P.S. I actually work at Jaycar so I can put a note into IT tomorrow stating the issue

I seem to have pinpointed the error. It's in the script "RequestHandlersImpl.h" as the error said. The current script is:

#ifndef REQUESTHANDLERSIMPL_H
#define REQUESTHANDLERSIMPL_H

#include <ESP8266WebServer.h>
#include "RequestHandler.h"
#include "mimetable.h"
#include "WString.h"

using namespace mime;

template<typename ServerType>
class FunctionRequestHandler : public RequestHandler<ServerType> {
    using WebServerType = ESP8266WebServerTemplate<ServerType>;
public:
    FunctionRequestHandler(typename WebServerType::THandlerFunction fn, typename WebServerType::THandlerFunction ufn, const String &uri, HTTPMethod method)
    : _fn(fn)
    , _ufn(ufn)
    , _uri(uri)
    , _method(method)
    {
    }

    bool canHandle(HTTPMethod requestMethod, String requestUri) override  {
        if (_method != HTTP_ANY && _method != requestMethod)
            return false;

        if (requestUri != _uri)
            return false;

        return true;
    }

    bool canUpload(String requestUri) override  {
        if (!_ufn || !canHandle(HTTP_POST, requestUri))
            return false;

        return true;
    }

    bool handle(WebServerType& server, HTTPMethod requestMethod, String requestUri) override {
        (void) server;
        if (!canHandle(requestMethod, requestUri))
            return false;

        _fn();
        return true;
    }

    void upload(WebServerType& server, String requestUri, HTTPUpload& upload) override {
        (void) server;
        (void) upload;
        if (canUpload(requestUri))
            _ufn();
    }

protected:
    typename WebServerType::THandlerFunction _fn;
    typename WebServerType::THandlerFunction _ufn;
    String _uri;
    HTTPMethod _method;
};

template<typename ServerType>
class StaticRequestHandler : public RequestHandler<ServerType> {
    using WebServerType = ESP8266WebServerTemplate<ServerType>;
public:
    StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header)
    : _fs(fs)
    , _uri(uri)
    , _path(path)
    , _cache_header(cache_header)
    {
        _isFile = fs.exists(path);
        DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header);
        _baseUriLength = _uri.length();
    }

    bool canHandle(HTTPMethod requestMethod, String requestUri) override  {
        if ((requestMethod != HTTP_GET) && (requestMethod != HTTP_HEAD))
            return false;

        if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri))
            return false;

        return true;
    }

    bool handle(WebServerType& server, HTTPMethod requestMethod, String requestUri) override {
        if (!canHandle(requestMethod, requestUri))
            return false;

        DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());

        String path(_path);

        if (!_isFile) {
            // Base URI doesn't point to a file.
            // If a directory is requested, look for index file.
            if (requestUri.endsWith("/")) 
              requestUri += "index.htm";

            // Append whatever follows this URI in request to get the file path.
            path += requestUri.substring(_baseUriLength);

            if (!_fs.exists(path) && path.endsWith(".htm") && _fs.exists(path + "l")) {
                path += "l";
            }
        }
        DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);

        String contentType = getContentType(path);

        // look for gz file, only if the original specified path is not a gz.  So part only works to send gzip via content encoding when a non compressed is asked for
        // if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc...
        if (!path.endsWith(FPSTR(mimeTable[gz].endsWith)) && !_fs.exists(path))  {
            String pathWithGz = path + FPSTR(mimeTable[gz].endsWith);
            if(_fs.exists(pathWithGz))
                path += FPSTR(mimeTable[gz].endsWith);
        }

        File f = _fs.open(path, "r");
        if (!f)
            return false;

        if (_cache_header.length() != 0)
            server.sendHeader("Cache-Control", _cache_header);

        server.streamFile(f, contentType, requestMethod);
        return true;
    }

    static String getContentType(const String& path) {
        char buff[sizeof(mimeTable[0].mimeType)];
        // Check all entries but last one for match, return if found
        for (size_t i=0; i < sizeof(mimeTable)/sizeof(mimeTable[0])-1; i++) {
            strcpy_P(buff, mimeTable[i].endsWith);
            if (path.endsWith(buff)) {
                strcpy_P(buff, mimeTable[i].mimeType);
                return String(buff);
            }
        }
        // Fall-through and just return default type
        strcpy_P(buff, mimeTable[sizeof(mimeTable)/sizeof(mimeTable[0])-1].mimeType);
        return String(buff);
    }

protected:
    FS _fs;
    String _uri;
    String _path;
    String _cache_header;
    bool _isFile;
    size_t _baseUriLength;
};


#endif //REQUESTHANDLERSIMPL_H

But the sector throwing errors is this:

StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header)
    : _fs(fs)
    , _uri(uri)
    , _path(path)
    , _cache_header(cache_header)
    {
        _isFile = fs.exists(path);
        DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header);
        _baseUriLength = _uri.length();
    }

This problem has gotten more complex than I thought it would. Personally I don't understand the syntax they used on this particular segment of code, so ANY help would be appreciated!

Ok, I found the problem after a few mintues of googling. Apparently in order to use the "ESP8266WebServer" library, for some arbitrary reason I don't understand, you have to also do "#include <FS.h>". Why isn't that part of the ESP8266WebServer library by default?!? As frustrated as I am at this annoying bug, at least hopefully I've helped someone in my frustration. I shall now go to IT and tell them how to fix the problem

Try updating to the latest version of the ESP8266 boards platform. I notice you're using the outdated version 2.6.3. Using the latest version (2.7.1), I can compile the unmodified sketch you posted without getting any errors. It may be that the issue causing your error has been fixed in the recent releases of the ESP8266 platform.