0

I am working on a smart IR receiver that reads an IR signal, decodes it and saves that decoded info in a json file stored on the NodeMCU's SPIFFS. This info is then displayed on the embedded web server in a table.

Now my problem is that even though I correctly save the signal's info in the json file (and when I try to print it in console it looks perfect), the son file is not correctly passed to my web server and the table remains empty. I am using jQuery to read the file and make the changes in the HTML. All the web server files (HTML, css & JavaScript) were tested first on my local machine with an example Json file of the same structure I am using on my SPIFFS so I know for sure the problem is not in there.

It is worth noting that I faced this problem when developing on my local machine, where the table would remain empty even though the json file is not, but it was fixed when I used the Live Server extension on VSCode. However, I don't understand if this is the problem how is it that there is no server to pass the json file on when all my web interface files are correctly passed and loaded from the SPIFFS.

I will include a portion of my code, and of course all help is appreciated.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h> 
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#include<FS.h>   // Include the SPIFFS library
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>

ESP8266WiFiMulti wifiMulti;     // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'

ESP8266WebServer server(80);    // Create a webserver object that listens for HTTP request on port 80

String getContentType(String filename); // convert the file extension to the MIME type
bool handleFileRead(String path);       // send the right file to the client (if it exists)

// Declaring a variable to hold JSON object size
//const size_t capacity = JSON_OBJECT_SIZE(10);

// Creating a JSON document to hold signal entry
//DynamicJsonDocument doc(capacity);

// Declaring array size
const size_t array_capacity = JSON_ARRAY_SIZE(16) + JSON_OBJECT_SIZE(1) + 16*JSON_OBJECT_SIZE(9);

// Creating a JSON document to hold all signal entries in a nested array
DynamicJsonDocument array_doc(array_capacity);

// Creating a nested JSON array to hold all signal entries
JsonArray signals = array_doc.createNestedArray("signals");

// Declaring a JSON object to hold single signal entry
JsonObject signal_entry;

// Declaring method that save JSON object to JSON file stored on SPIFFS
void saveJSON();

// Declaring method that prints JSON file stored on SPIFFS
void printJSON();

void setup(void){
  Serial.begin(115200);         // Start the Serial communication to send messages to the computer
  delay(10);
  Serial.println('\n');

  Serial.println("Connecting ...");
  int i = 0;
  while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect: scan for Wi-Fi networks, and connect to the strongest of the networks above
    delay(250);
    Serial.print('.');
  }

SPIFFS.begin();                           // Start the SPI Flash Files System 
   
  server.begin();                           // Actually start the server
  Serial.println("HTTP server started");

  server.onNotFound([]() {                              // If the client requests any URI
    if (!handleFileRead(server.uri()))                  // send it if it exists
      server.send(404, "text/plain", "404: Not Found"); // otherwise, respond with a 404 (Not Found) error
  });

void loop(void){
  server.handleClient();                    // Listen for HTTP requests from clients

//Creating a JSON object from the JSON document
    signal_entry = signals.createNestedObject();

    //Assigning correct values to keys in JSON object
    signal_entry["date"] = currentDate;
    signal_entry["protocol_type"] = protocol_type;
    signal_entry["bitNr_device"] = bitNr_device;
    signal_entry["bitNr_op"] = bitNr_op;
    signal_entry["codeDec_device"] = codeDec_device;
    signal_entry["codeDec_op"] = codeDec_op;
    signal_entry["codeHex_device"] = codeHex_device;
    signal_entry["codeHex_op"] = codeHex_op;
    signal_entry["codeBin_device"] = codeBin_device;
    signal_entry["codeBin_op"] = codeBin_op;
    
    serializeJsonPretty(signal_entry, Serial); 
    Serial.println("");
    
    saveJSON();
   }
}

String getContentType(String filename) { // convert the file extension to the MIME type
  if (filename.endsWith(".html")) return "text/html";
  else if (filename.endsWith(".css")) return "text/css";
  else if (filename.endsWith(".js")) return "application/javascript";
  else if (filename.endsWith(".ico")) return "image/x-icon";
  return "text/plain";
}

bool handleFileRead(String path) { // send the right file to the client (if it exists)
  Serial.println("handleFileRead: " + path);
  if (path.endsWith("/")) path += "index.html";         // If a folder is requested, send the index file
  String contentType = getContentType(path);            // Get the MIME type
  if (SPIFFS.exists(path)) {                            // If the file exists
    File file = SPIFFS.open(path, "r");                 // Open it
    size_t sent = server.streamFile(file, contentType); // And send it to the client
    file.close();                                       // Then close the file again
    return true;
  }
  Serial.println("\tFile Not Found");
  return false;                                         // If the file doesn't exist, return false
}

void saveJSON(){
  File jsonFile = SPIFFS.open("signals.json", "w");
  if (serializeJsonPretty(array_doc, jsonFile) == 0) {
    Serial.println("Failed to write to file");
  }
  jsonFile.close();
}

void printJSON(){
  uint8_t* pBuffer;
  File testFile = SPIFFS.open("signals.json", "r");
  if(testFile){
    unsigned int fileSize = testFile.size();
    pBuffer = (uint8_t*)malloc(fileSize + 1);
    testFile.read(pBuffer, fileSize);
    pBuffer[fileSize] = '\0';
    Serial.println((char*)pBuffer);                // Print the file to the serial monitor.
    testFile.close();
  }
  else{
    Serial.println("Failed to read to file");
  }
  free(pBuffer);
}

4
  • I think you messed your copying and pasting up. Your loop() function seems to be in the middle of your setup() function. – Majenko Aug 29 '20 at 13:46
  • It sound like you are running the webpage on you PC, but getting the json from the ESP. Browsers don't like that, as it's some form of cross-site scripting. It can work if the ESP also sends the correct permission headers. Access-Control-Allow-Origin: * to be specific. You also might want to open the developer console in your browser to see if any errors pop up. Also check the network tab to see if the json gets requested. – Gerben Aug 29 '20 at 16:03
  • @Gerben I am not quite sure I understand what you mean, my web page is hosted on the ESP and I access it via the IP address, however, in the JS file linked to my HTML (Both stored on SPIFFS btw) I look for the json file in the same folder as my web page, is this the problem? And I checked the dev tools, yes the json file is requested and the request has a status 200 OK. – Mo'men Alaswad Aug 30 '20 at 14:12
  • Never mind. The VSCode extension part threw me of, but apparently that's not the issue here. – Gerben Aug 30 '20 at 18:18
1

Besides the somewhat strange problem of loop() being nested inside setup() (which I will put down to a copy-and-paste error) I think your main problem is that of a lack of content-type.

The function getContentType() is supposed to guess the content type by the filename extension. However there is nothing there to handle a .json file. So it will just default to text/plain - which won't be interpreted as JSON data.

You need to add a bit in there to look for JSON files and set the content-type accordingly:

...
} else if (filename.endsWith(".json")) {
    return "application/json";
}
3
  • I tried it, but sadly this was not it. In the browser dev tools, the json file is requested and the request is accepted, however, the table remains empty even though the json file is not. – Mo'men Alaswad Aug 30 '20 at 14:09
  • Then there is something wrong with your website code. – Majenko Aug 30 '20 at 14:25
  • try coping the response and manually parsing it with JSON.parse(). – dandavis Aug 31 '20 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.