IDE mistakes JavaScript function for type

Maybe my eye is skipping over something but it looks like the IDE thinks that the functions are types. I don't really want to put the HTML into a separate file, so I have no idea how to work around this. Any tip is greatly appreciated.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
*********/

// Import required libraries
#include <WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Data wire is connected to GPIO 4
#define ONE_WIRE_BUS 32

                                                                                            //TO DO LIST
//values for controlling temperatures
//controlling the relays
bool Relay1Status = LOW;
uint8_t Relay1Pin = 13;
//input from the web interface
int TargetTemp  = 0;
String TargetTempStr = String(TargetTemp);
int MinTemp = TargetTemp - 1;
int MaxTemp = TargetTemp + 1;
//404 if server can't respond
void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}



                                                                                //Assingning values and setting up 

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);

// Variables to store temperature values
String temperatureF = "";
String temperatureC = "";
int TempNum;
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 3000;

// Replace with your network credentials
const char* ssid = "Telekom-d86e0e-2.4GHz";
const char* password = "KH9HENFUETJ5";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

                                                                               

                                                                               //Reading DS18B20 Temperature

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0);

  if (tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC);
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures();
  float tempF = sensors.getTempFByIndex(0);

  if (int(tempF) == -196) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

                                                                                
                                                                                
                                                                                //HTML page

const char index_html[] PROGMEM = R"rawliteral(
    <!DOCTYPE HTML><html>
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" crossorigin="anonymous">
      <style>
        html {
         font-family: Arial;
         display: inline-block;
         margin: 0px auto;
         text-align: center;
        }
        h2 { font-size: 3.0rem; }
        p { font-size: 3.0rem; }
        .units { font-size: 1.2rem; }
        .ds-labels{
          font-size: 1.5rem;
          vertical-align:middle;
          padding-bottom: 15px;
        }
      </style>
    </head>
    <body>
      <h2>ESP DS18B20 Server</h2>
      <p>
        <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
        <span class="ds-labels">Temperature Celsius</span> 
        <span id="temperaturec">%TEMPERATUREC%</span>
        <sup class="units">&deg;C</sup>
      </p>
      <p>
        <h3> Target Temperature </h3>
        <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
        <span class="ds-labels"></span> 
        <span id="TargetTemp">%TARGETTEMPERATURE%</span>
        <sup class="units">&deg;C</sup>
        
        <button class = "addingButton" onclick = addToInt()"> + </button>
        <button class = "subtractingButton" onclick = subFromInt()"> + </button>
      </p>    
    </body>
    <script>
      setInterval(function ( ) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            document.getElementById("temperaturec").innerHTML = this.responseText;
          }
        };
        xhttp.open("GET", "/temperaturec", true);
        xhttp.send();
      }, 10000) ;
                      
      setInterval(function ( ) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            document.getElementById("TargetTemp").innerHTML = this.responseText;
          }
        };
        xhttp.open("GET", "/TargetTemp", true);
        xhttp.send();
      }, 10000) ;
      
       function addToInt(){
          var xhr = new XMLHttpRequest();
          xhr.open("GET", "/add", true);
          xhr.send();
       }
       function subFromInt(){
          var xhr = new XMLHttpRequest();
          xhr.open("GET", "/subtract", true);
          xhr.send();
       }
    </script>
    </html>)rawliteral";

// Replaces placeholder with DS18B20 values
String processor(const String& var) {
  //Serial.println(var);
  if (var == "TEMPERATUREC") {
    return temperatureC;                                                        
  }
  else if (var == "TEMPERATUREF") {
    return temperatureF;
  }
   if (var == "TARGETTEMPERATURE") {
    return String(TargetTemp);                                                        
  }
  return String();
}

void setup() {
  pinMode(13,OUTPUT);
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();

  // Start up the DS18B20 library
  sensors.begin();

  temperatureC = readDSTemperatureC();
  temperatureF = readDSTemperatureF();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/plain", temperatureC.c_str());
  });
  server.on("/TargetTemp", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/plain", TargetTempStr.c_str());                                             
  });
      // Start server
  server.begin();

  server.on("/add", HTTP_GET, [](AsyncWebServerRequest * request) {
    TargetTemp++;
    request->send(200, "text/plain", "ok");
  });
  server.on("/subtract", HTTP_GET, [](AsyncWebServerRequest * request) {
    TargetTemp--;
    request->send(200, "text/plain", "ok");
  });




});
}
void loop() {
  if ((millis() - lastTime) > timerDelay) {
    temperatureC = readDSTemperatureC();
    temperatureF = readDSTemperatureF();
    lastTime = millis();
  }
  TempNum = readDSTemperatureC().toInt();
  if (TempNum > MaxTemp) {
    digitalWrite(13, LOW);
  }
  if (MinTemp > TempNum) {
    digitalWrite(13, HIGH);
  }
  Serial.println(TempNum);
  delay(1000);
}

Arduino: 1.8.17 Hourly Build 2021/09/06 02:33 (Windows 10), Board: "NodeMCU-32S, 80MHz, 921600"

sketch_dec23a:158:1: error: 'function' does not name a type

    function addToInt(){

^

sketch_dec23a:163:1: error: 'function' does not name a type

    function subFromInt(){

^

sketch_dec23a:235:2: error: expected unqualified-id before ')' token

});

^

sketch_dec23a:236:1: error: expected declaration before '}' token

}

^

Multiple libraries were found for "WiFi.h"

Used: C:\Users\hunya\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi

Not used: C:\Users\hunya\Documents,\Arduino\arduino-nightly\libraries\WiFi

Multiple libraries were found for "AsyncTCP.h"

Used: C:\Users\hunya\Documents\Arduino\libraries\AsyncTCP

Not used: C:\Users\hunya\Documents,\Arduino\arduino-nightly\libraries\AsyncTCP

Multiple libraries were found for "ESPAsyncWebServer.h"

Used: C:\Users\hunya\Documents,\Arduino\arduino-nightly\libraries\ESPAsyncWebServer

Not used: C:\Users\hunya\Documents\Arduino\libraries\ESPAsyncWebServer-master

exit status 1

'function' does not name a type

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

1 Like

Runs fine sketch.ino - Wokwi Arduino and ESP32 Simulator

I vaguely suspect that the Arduino pre-processing doesn't know about raw string literals, and things blow up when it generates prototypes for what it THINKS are functions inside the string.

Putting the literal in a separate .h file seems like an easy solution.

1 Like

I distilled it down to this minimal demo:

void foo() {}
const char someRawString[] = R"rawliteral(
    ";
    notArduinoType notArduinoFunction() {}
  )rawliteral";
void setup() {}
void loop() {}

After sketch preprocessing, the code looks like this:

#include <Arduino.h>
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved2022029-6972-afm1mj.bko1\\sketch_jan29a\\sketch_jan29a.ino"
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved2022029-6972-afm1mj.bko1\\sketch_jan29a\\sketch_jan29a.ino"
void foo();
#line 4 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved2022029-6972-afm1mj.bko1\\sketch_jan29a\\sketch_jan29a.ino"
notArduinoType notArduinoFunction();
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved2022029-6972-afm1mj.bko1\\sketch_jan29a\\sketch_jan29a.ino"
void foo() {}
const char someRawString[] = R"rawliteral(
    ";
    notArduinoType notArduinoFunction() {}
  )rawliteral";
void setup() {}
void loop() {}

So as westfw hypothesized, the sketch preprocessor generated a function prototype for the things resembling a C++ function from the raw string literal.


There are some previous mentions of sketch preprocessor misbehaving in sketches that have specific raw string literal content here:

and here:

Note the comment from the developer there:

It's ctags that is not able to correctly parse multil-line raw literals.
It's unlikely that this will be fixed upstream (at least not soon).

A workaround may be to put the strings inside a .h file (that is not preprocessed) and include it from the main .ino.

It knows, I successfully used it with MKR WiFi to output html page

The bug only happens under specific conditions. For example, this one compiled successfully:

But add a function definition above the raw string declaration, and you will see the error reported by javamakesmybloodboil:
https://wokwi.com/arduino/projects/322205654555034195

Try adding

void notFound(AsyncWebServerRequest *request);
String readDSTemperatureC();
String readDSTemperatureF();

At the top of the sketch

That automatic prototype generation probably sounded like a nice newbie-friendly feature when it was first dreamed up but has had far reaching consequences and is a perfect example of the risks of altering language features.

Fortunately, its behaviour is restricted to .ino files. Of course, you can get around this by restructuring the sketch and moving stuff out of the ino file. That is once you understand what has happened and, hopefully, before too much agonising troubleshooting.

1 Like

Another way to work around this problem with the Arduino automatic prototype generation is to put:
typedef void function;
at the top of the source code. Then the two prototypes that look like:

  function addToInt();
  function subFromInt();

will know that the 'function' type is the same as 'void'.

This example compiles without error:

typedef void function;

void foo() {}

const char someRawString[] = R"rawliteral(";
  function addToInt() {}
  function subFromInt() {}
")rawliteral";
 
void setup() {}
void loop() {}

edit: it works but the code example does not (not with visual macro)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.