Problem when include lcd library

Hi,

I have a problem when running a code. I have an Arduino Uno and an LCD Display.

The code works perfectly fine, when I run it without this part of the code:

#include "rgb_lcd.h"

But after I put it in the code, it stops at the part, where I print "Making POST Request"

Here is my whole code:

#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoHttpClient.h>
#include <stdio.h>
#include <string.h>

char ssid[] = "iPhone 14 Pro von Andrin"; // your network SSID (name)
char pass[] = "12345678"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;          // your network key index number (needed only for WEP)

char serverAddress[] = "172.20.10.2"; // server address from Wifi. You can look up this adress in the settings
int port = 8080;
WiFiServer server(80);

DynamicJsonDocument postMessage(1048);
String jsonBody;
String contentType = "application/json";

DynamicJsonDocument doc(900);

WiFiClient wifi;
HttpClient http = HttpClient(wifi, serverAddress, port);

/**
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
**/

char webpage[] = R"=====(
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SBB Fahrplan</title>
</head>

<body>
    <script>
        const handleSubmit = () => {
            const radioButtons = document.querySelectorAll('input[name="zug"]');

            const abfahrt = document.getElementById('abfahrt').value
            const ankunft = document.getElementById('ankunft').value
            
            let selectedButton;

            for (const radioButton of radioButtons) {
                if (radioButton.checked) {
                    selectedButton = radioButton.value;
                    if (selectedButton === 'false') {
                        selectedButton = false
                    }

                    if (selectedButton === 'true') {
                        selectedButton = true
                    }
                }
            }

            var myHeaders = new Headers();
            myHeaders.append("Content-Type", "application/json");

            var raw = JSON.stringify({
                from: abfahrt,
                to: ankunft,
                lastOne: selectedButton
            });

            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: raw,
                redirect: 'follow'
            };

            fetch("http://localhost:8080/getDataByTrip", requestOptions)
                .then(response => response.json())
                .then(result => console.log(result)) 
                .then(fetch(`http://172.20.10.8/H?from=${abfahrt}&to=${ankunft}&lastOne=${selectedButton}`, {
                    method: "GET"
                }))
        }
    </script>
    <h2>SBB Fahrplan</h2>

    <label for="abbh">Abfahrts Bahnhof:</label>
    <input type="text" id="abfahrt" name="Abfahrts Bahnhof" placeholder="Abfahrts Bahnhof">

    <label for="anbh">Ankunfts Bahnhof:</label>
    <input type="text" id="ankunft" name="Ankunfts Bahnhof" placeholder="Ankunfts Bahnhof">

    <input type="radio" id="nzug" name="zug" value="false">
    <label for="nzug">nächster Zug</label>
    <input type="radio" id="lzug" name="zug" value="true">
    <label for="lzug">letzter Zug</label>
    <br><br>
    <button onclick="handleSubmit()">ok</button>

</body>

</html>
)=====";

void printWifiStatus()
{
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

    // print your board's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);

    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
    // print where to go in a browser:
    Serial.print("To see this page in action, open a browser to http://");
    Serial.println(ip);
}

void percentDecode(char *src)
{
    char *dst = src;

    while (*src)
    {
        if (*src == '+')
        {
            src++;
            *dst++ = ' ';
        }
        else if (*src == '%')
        {
            // handle percent escape

            *dst = '\0';
            src++;

            if (*src >= '0' && *src <= '9')
            {
                *dst = *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst = 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst = 10 + *src++ - 'a';
            }
            
            *dst <<= 4;

            if (*src >= '0' && *src <= '9')
            {
                *dst |= *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst |= 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst |= 10 + *src++ - 'a';
            }

            dst++;
        }
        else
        {
            *dst++ = *src++;
        }
    }
    *dst = '\0';
}

int parseUrlParams(char *queryString, char *results[][2], int resultsMaxCt, boolean decodeUrl)
{
    int ct = 0;

    while (queryString && *queryString && ct < resultsMaxCt)
    {
        results[ct][0] = strsep(&queryString, "&");
        results[ct][1] = strchrnul(results[ct][0], '=');
        if (*results[ct][1])
            *results[ct][1]++ = '\0';

        if (decodeUrl)
        {
            percentDecode(results[ct][0]);
            percentDecode(results[ct][1]);
        }

        ct++;
    }

    return ct;
}

int status = WL_IDLE_STATUS;

void setup()
{ 
    Serial.begin(9600); // initialize serial communication
    pinMode(9, OUTPUT); // set the LED pin mode
    
    // check for the WiFi module:
    if (WiFi.status() == WL_NO_MODULE)
    {
        Serial.println("Communication with WiFi module failed!");
        // don't continue
        while (true)
            ;
    }

    String fv = WiFi.firmwareVersion();
    if (fv < WIFI_FIRMWARE_LATEST_VERSION)
    {
        Serial.println("Please upgrade the firmware");
    }

    // attempt to connect to WiFi network:
    while (status != WL_CONNECTED)
    {
        Serial.print("Attempting to connect to Network named: ");
        Serial.println(ssid); // print the network name (SSID);

        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);
        // wait 10 seconds for connection:
        delay(10000);
    }
    server.begin();    // start the web server on port 80
    printWifiStatus(); // you're connected now, so print out the status
    /**
    lcd.begin(16, 2);
    lcd.setRGB(colorR, colorG, colorB);
    **/
}

char url[70];

boolean done = false;

char responseCopy = "";

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

    char buf[100];
    char *params[5][2];

    if (client)
    {                                 // if you get a client,
        Serial.println("new client"); // print a message out the serial port
        String currentLine = "";      // make a String to hold incoming data from the client
        String httpGetUrl = "";
        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 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)
                    {
                        // 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();

                        // the content of the HTTP response follows the header:
                        // client.print("Click <a href=\"/H\">here</a> turn the LED on pin 9 on<br>");
                        client.print(webpage);

                        // 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
                }
                else
                {

                    if (currentLine.startsWith("GET /H?from="))
                    {

                        httpGetUrl += currentLine;

                        httpGetUrl.remove(0, 7);
                        int http = httpGetUrl.indexOf(" HTTP/1.1");
                        httpGetUrl.remove(http, 9);

                        httpGetUrl.toCharArray(url, 100);

                        char *tests[] = {
                            url,
                        };

                        for (int i = 0; i < sizeof(tests) / sizeof(*tests); i++)
                        {
                            Serial.print("parsing \"");
                            Serial.print(tests[i]);

                            // copy test[i] into the buffer
                            // because the parser overwrites what is i the string it is passed.
                            strcpy(buf, tests[i]);

                            // parse the buffer into params[][]
                            int resultsCt = parseUrlParams(buf, params, 5, true);

                            // print off the results;

                            Serial.print("\" produced ");
                            Serial.print(resultsCt);
                            Serial.print(" parameters:");
                            Serial.println();

                            for (int i = 0; i < resultsCt; i++)
                            {
                                Serial.print("param ");
                                Serial.print(i);
                                Serial.print(" name \"");
                                Serial.print(params[i][0]);
                                Serial.print("\", param \"");
                                Serial.print(params[i][1]);
                                Serial.print("\".");
                                Serial.println();
                                postMessage["from"] = params[0][1];
                                postMessage["to"] = params[0][3];
                                postMessage["lastOne"] = params[0][5];
                            }

                            serializeJson(postMessage, jsonBody);

                            Serial.print("Json Body: ");
                            Serial.println(jsonBody);

                            Serial.println("making POST request");

                            done = true;
                        }
                    }
                }

                // Check to see if the client request was "GET /H" or "GET /L":
                //  if (currentLine.endsWith("GET /H")) {
                while (done)
                {
                    http.post("/getDataByTrip", contentType, jsonBody);

                    // read the status code and body of the response
                    int statusCode = http.responseStatusCode();
                    String responseRequest = http.responseBody();

                    Serial.print("Status code: ");
                    Serial.println(statusCode);
                    Serial.print("Response: ");
                    Serial.println(responseRequest);

                    DeserializationError error = deserializeJson(doc, responseRequest);

                    if (error) {
                      Serial.print(F("deserializeJson() failed: "));
                      Serial.println(error.f_str());
                      return;
                    }

                    const char* from = doc["from"];
                    const char* toTrain = doc["to"];
                    int gleis = doc["gleis"];
                    int lateInMinutes = doc["lateInMinutes"];
                    const char* departure = doc["departure"];
                    int waggonsCount = doc["waggonsCount"];

                    Serial.print("To Request: ");
                    Serial.println(toTrain);

                    jsonBody = "";
               
                    
                    if (responseRequest.length() > 10)
                    {
                        done = false;
                    }
                    else
                    {

                        done = false;
                    }
                    responseRequest = "";
/**
                    lcd.print("Zurich HB");
                    lcd.print(" - ");
                    **/
                }
                //}
            }
        }
        // close the connection:
        client.stop();
        Serial.println("client disconnected");
    }
}

You forgot to tell us what board you're using. As you're using the WiFiNINA library it's most probably not the Arduino UNO we usually assume if one doesn't explicitly mentions.

My guess is: out of memory. You might try the F() macro as you have tons of strings that might be read directly from the flash.

Thanks for your answer.

I am endeed using the Arduino UNO and I have enough memory I think. In the console it says that I have 60% memory used. So I don‘t think that this is the problem.

I don‘t know why but as soon as I Include the library it doesn‘t work anymore. Really strange

UNO or "UNO Wifi Rev2", there are major differences between those boards (one major difference being the UNO Wifi Rev2 actually works with WiFiNINA).

Do the example sketches for the rgb_lcd library run properly? If you are using the UNO WiFi Rev2 board, there are quite a few libraries that are going to be incompatible.

Thank you for the answer. Yes you are right I have a UNO WiFi Rev2. Yeah the example of this library works fine without problem.

The UNO WiFi Rev2 is a completely different board than the UNO. The only things they have in common is part of the name, the operating voltage and the board layout. They have a different processor, different on-board devices and completely different features. I think Arduino did a major mistake to use the name UNO for the UNO WiFi Rev2 again.

Although the ATmega4809 has three times the RAM of the ATmega328p in the UNO you must probably run out of it. You HTML code only uses more RAM than the UNO has in total. As I wrote earlier: Learn to use the F() macro to keep the literal strings in the flash and don't waste RAM for them.

1 Like

No need for the F() macro, the compiler will put constants in flash memory automatically with the atmega4809.

Does the inclusion of just the library header cause the problem, or are you adding more code?

Yes I just include the library at the top to the others. I commented the code to this library out.

I notice you have the following:

char url[70];

Then later:

                        httpGetUrl.toCharArray(url, 100);

                        char *tests[] = {
                            url,
                        };

                        for (int i = 0; i < sizeof(tests) / sizeof(*tests); i++)
                        {
                            Serial.print("parsing \"");
                            Serial.print(tests[i]);

Copying 100 characters into a 70 character buffer can't be good. I'm also a bit confused about the tests array and the size calculation in the for statement.

I put the url into this char, because then I can parse the GET-Request right. I couldn't find another good solution to parse a GET-Request.

The char array itself is not the problem, putting up to 100 characters into an array that can only hold 70 is.

So I fixed that now with the char, but unfortunately it still don't work. It's weird when I put in the library, the JSON document I want to send is not completely a json document. Here is what I mean, because I print it out:

parsing "from=Bern&to=Zurich-HB&lastOne=false" produced 3 parameters:
param 0 name "from", param "Bern".
param 1 name "to", param "Zurich-HB".
param 2 name "lastOne", param "false".
Json Body: {"from":"Bern","to":"Zurich-HB"

One parameter and this } is missing too.

My code:

#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoHttpClient.h>
#include <stdio.h>
#include <string.h>
#include "rgb_lcd.h"

char ssid[] = "iPhone 14 Pro von Andrin"; // your network SSID (name)
char pass[] = "12345678"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;          // your network key index number (needed only for WEP)

char serverAddress[] = "172.20.10.2"; // server address from Wifi. You can look up this adress in the settings
int port = 8080;
WiFiServer server(80);

DynamicJsonDocument postMessage(1048);
String jsonBody;
String contentType = "application/json";

DynamicJsonDocument doc(900);

WiFiClient wifi;
HttpClient http = HttpClient(wifi, serverAddress, port);

char webpage[] = R"=====(
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SBB Fahrplan</title>
</head>

<body>
    <script>
        const handleSubmit = () => {
            const radioButtons = document.querySelectorAll('input[name="zug"]');

            const abfahrt = document.getElementById('abfahrt').value
            const ankunft = document.getElementById('ankunft').value
            
            let selectedButton;

            for (const radioButton of radioButtons) {
                if (radioButton.checked) {
                    selectedButton = radioButton.value;
                    if (selectedButton === 'false') {
                        selectedButton = false
                    }

                    if (selectedButton === 'true') {
                        selectedButton = true
                    }
                }
            }

            var myHeaders = new Headers();
            myHeaders.append("Content-Type", "application/json");

            var raw = JSON.stringify({
                from: abfahrt,
                to: ankunft,
                lastOne: selectedButton
            });

            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: raw,
                redirect: 'follow'
            };

            fetch("http://localhost:8080/getDataByTrip", requestOptions)
                .then(response => response.json())
                .then(result => console.log(result)) 
                .then(fetch(`http://172.20.10.8/H?from=${abfahrt}&to=${ankunft}&lastOne=${selectedButton}`, {
                    method: "GET"
                }))
        }
    </script>
    <h2>SBB Fahrplan</h2>

    <label for="abbh">Abfahrts Bahnhof:</label>
    <input type="text" id="abfahrt" name="Abfahrts Bahnhof" placeholder="Abfahrts Bahnhof">

    <label for="anbh">Ankunfts Bahnhof:</label>
    <input type="text" id="ankunft" name="Ankunfts Bahnhof" placeholder="Ankunfts Bahnhof">

    <input type="radio" id="nzug" name="zug" value="false">
    <label for="nzug">nächster Zug</label>
    <input type="radio" id="lzug" name="zug" value="true">
    <label for="lzug">letzter Zug</label>
    <br><br>
    <button onclick="handleSubmit()">ok</button>

</body>

</html>
)=====";

void printWifiStatus()
{
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

    // print your board's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);

    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
    // print where to go in a browser:
    Serial.print("To see this page in action, open a browser to http://");
    Serial.println(ip);
}

void percentDecode(char *src)
{
    char *dst = src;

    while (*src)
    {
        if (*src == '+')
        {
            src++;
            *dst++ = ' ';
        }
        else if (*src == '%')
        {
            // handle percent escape

            *dst = '\0';
            src++;

            if (*src >= '0' && *src <= '9')
            {
                *dst = *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst = 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst = 10 + *src++ - 'a';
            }
            
            *dst <<= 4;

            if (*src >= '0' && *src <= '9')
            {
                *dst |= *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst |= 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst |= 10 + *src++ - 'a';
            }

            dst++;
        }
        else
        {
            *dst++ = *src++;
        }
    }
    *dst = '\0';
}

int parseUrlParams(char *queryString, char *results[][2], int resultsMaxCt, boolean decodeUrl)
{
    int ct = 0;

    while (queryString && *queryString && ct < resultsMaxCt)
    {
        results[ct][0] = strsep(&queryString, "&");
        results[ct][1] = strchrnul(results[ct][0], '=');
        if (*results[ct][1])
            *results[ct][1]++ = '\0';

        if (decodeUrl)
        {
            percentDecode(results[ct][0]);
            percentDecode(results[ct][1]);
        }

        ct++;
    }

    return ct;
}

int status = WL_IDLE_STATUS;

void setup()
{ 
    Serial.begin(9600); // initialize serial communication
    pinMode(9, OUTPUT); // set the LED pin mode
    
    // check for the WiFi module:
    if (WiFi.status() == WL_NO_MODULE)
    {
        Serial.println("Communication with WiFi module failed!");
        // don't continue
        while (true)
            ;
    }

    String fv = WiFi.firmwareVersion();
    if (fv < WIFI_FIRMWARE_LATEST_VERSION)
    {
        Serial.println("Please upgrade the firmware");
    }

    // attempt to connect to WiFi network:
    while (status != WL_CONNECTED)
    {
        Serial.print("Attempting to connect to Network named: ");
        Serial.println(ssid); // print the network name (SSID);

        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);
        // wait 10 seconds for connection:
        delay(10000);
    }
    server.begin();    // start the web server on port 80
    printWifiStatus(); // you're connected now, so print out the status
}

char url[100];

boolean done = false;

char responseCopy = "";

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

    char buf[100];
    char *params[5][2];

    if (client)
    {                                 // if you get a client,
        Serial.println("new client"); // print a message out the serial port
        String currentLine = "";      // make a String to hold incoming data from the client
        String httpGetUrl = "";
        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 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)
                    {
                        // 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();

                        // the content of the HTTP response follows the header:
                        // client.print("Click <a href=\"/H\">here</a> turn the LED on pin 9 on<br>");
                        client.print(webpage);

                        // 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
                }
                else
                {

                    if (currentLine.startsWith("GET /H?from="))
                    {

                        httpGetUrl += currentLine;

                        httpGetUrl.remove(0, 7);
                        int http = httpGetUrl.indexOf(" HTTP/1.1");
                        httpGetUrl.remove(http, 9);

                        httpGetUrl.toCharArray(url, 100);

                        char *tests[] = {
                            url,
                        };

                        for (int i = 0; i < sizeof(tests) / sizeof(*tests); i++)
                        {
                            Serial.print("parsing \"");
                            Serial.print(tests[i]);

                            // copy test[i] into the buffer
                            // because the parser overwrites what is i the string it is passed.
                            strcpy(buf, tests[i]);

                            // parse the buffer into params[][]
                            int resultsCt = parseUrlParams(buf, params, 5, true);

                            // print off the results;

                            Serial.print("\" produced ");
                            Serial.print(resultsCt);
                            Serial.print(" parameters:");
                            Serial.println();

                            for (int i = 0; i < resultsCt; i++)
                            {
                                Serial.print("param ");
                                Serial.print(i);
                                Serial.print(" name \"");
                                Serial.print(params[i][0]);
                                Serial.print("\", param \"");
                                Serial.print(params[i][1]);
                                Serial.print("\".");
                                Serial.println();
                                postMessage["from"] = params[0][1];
                                postMessage["to"] = params[0][3];
                                postMessage["lastOne"] = params[0][5];
                            }

                            serializeJson(postMessage, jsonBody);

                            Serial.print("Json Body: ");
                            Serial.println(jsonBody);

                            Serial.println("making POST request");

                            done = true;
                        }
                    }
                }

                // Check to see if the client request was "GET /H" or "GET /L":
                //  if (currentLine.endsWith("GET /H")) {
                while (done)
                {
                    http.post("/getDataByTrip", contentType, jsonBody);

                    // read the status code and body of the response
                    int statusCode = http.responseStatusCode();
                    String responseRequest = http.responseBody();

                    Serial.print("Status code: ");
                    Serial.println(statusCode);
                    Serial.print("Response: ");
                    Serial.println(responseRequest);

                    DeserializationError error = deserializeJson(doc, responseRequest);

                    if (error) {
                      Serial.print(F("deserializeJson() failed: "));
                      Serial.println(error.f_str());
                      return;
                    }

                    const char* from = doc["from"];
                    const char* toTrain = doc["to"];
                    int gleis = doc["gleis"];
                    int lateInMinutes = doc["lateInMinutes"];
                    const char* departure = doc["departure"];
                    int waggonsCount = doc["waggonsCount"];

                    Serial.print("To Request: ");
                    Serial.println(toTrain);

                    jsonBody = "";
               
                    
                    if (responseRequest.length() > 10)
                    {
                        done = false;
                    }
                    else
                    {

                        done = false;
                    }
                    responseRequest = "";
                }
                //}
            }
        }
        // close the connection:
        client.stop();
        Serial.println("client disconnected");
    }
}
                                postMessage["from"] = params[0][1];
                                postMessage["to"] = params[0][3];
                                postMessage["lastOne"] = params[0][5];

Take a look at the indices. You should stay inside the limits!

Why is that block inside the loop?

Thanks for your answer

Yes I exactly mean this. That this is also missing and because of that it is not a json document and my backend can‘t read it.

I changed the code and now I think it is correct with the params Array and I am in the limit of that array. But it still not works.

I have also included the code for printing a test hello world to the lcd and this works until the same point as I explained above.

#include <SPI.h>
#include <Wire.h>
#include "rgb_lcd.h"
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoHttpClient.h>
#include <stdio.h>
#include <string.h>

char ssid[] = "iPhone 14 Pro von Andrin"; // your network SSID (name)
char pass[] = "12345678"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;          // your network key index number (needed only for WEP)

rgb_lcd lcd;

const int colorR = 255;
const int colorG = 0;
const int colorB = 0;


char serverAddress[] = "172.20.10.2"; // server address from Wifi. You can look up this adress in the settings
int port = 8080;
WiFiServer server(80);

DynamicJsonDocument postMessage(1048);
String jsonBody;
String contentType = "application/json";

DynamicJsonDocument doc(900);

WiFiClient wifi;
HttpClient http = HttpClient(wifi, serverAddress, port);

char webpage[] = R"=====(
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SBB Fahrplan</title>
</head>

<body>
    <script>
        const handleSubmit = () => {
            const radioButtons = document.querySelectorAll('input[name="zug"]');

            const abfahrt = document.getElementById('abfahrt').value
            const ankunft = document.getElementById('ankunft').value
            
            let selectedButton;

            for (const radioButton of radioButtons) {
                if (radioButton.checked) {
                    selectedButton = radioButton.value;
                    if (selectedButton === 'false') {
                        selectedButton = false
                    }

                    if (selectedButton === 'true') {
                        selectedButton = true
                    }
                }
            }

            var myHeaders = new Headers();
            myHeaders.append("Content-Type", "application/json");

            var raw = JSON.stringify({
                from: abfahrt,
                to: ankunft,
                lastOne: selectedButton
            });

            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: raw,
                redirect: 'follow'
            };

            fetch("http://localhost:8080/getDataByTrip", requestOptions)
                .then(response => response.json())
                .then(result => console.log(result)) 
                .then(fetch(`http://172.20.10.8/H?from=${abfahrt}&to=${ankunft}&lastOne=${selectedButton}`, {
                    method: "GET"
                }))
        }
    </script>
    <h2>SBB Fahrplan</h2>

    <label for="abbh">Abfahrts Bahnhof:</label>
    <input type="text" id="abfahrt" name="Abfahrts Bahnhof" placeholder="Abfahrts Bahnhof">

    <label for="anbh">Ankunfts Bahnhof:</label>
    <input type="text" id="ankunft" name="Ankunfts Bahnhof" placeholder="Ankunfts Bahnhof">

    <input type="radio" id="nzug" name="zug" value="false">
    <label for="nzug">nächster Zug</label>
    <input type="radio" id="lzug" name="zug" value="true">
    <label for="lzug">letzter Zug</label>
    <br><br>
    <button onclick="handleSubmit()">ok</button>

</body>

</html>
)=====";

void printWifiStatus()
{
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

    // print your board's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);

    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
    // print where to go in a browser:
    Serial.print("To see this page in action, open a browser to http://");
    Serial.println(ip);
}

void percentDecode(char *src)
{
    char *dst = src;

    while (*src)
    {
        if (*src == '+')
        {
            src++;
            *dst++ = ' ';
        }
        else if (*src == '%')
        {
            // handle percent escape

            *dst = '\0';
            src++;

            if (*src >= '0' && *src <= '9')
            {
                *dst = *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst = 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst = 10 + *src++ - 'a';
            }
            
            *dst <<= 4;

            if (*src >= '0' && *src <= '9')
            {
                *dst |= *src++ - '0';
            }
            else if (*src >= 'A' && *src <= 'F')
            {
                *dst |= 10 + *src++ - 'A';
            }
            else if (*src >= 'a' && *src <= 'f')
            {
                *dst |= 10 + *src++ - 'a';
            }

            dst++;
        }
        else
        {
            *dst++ = *src++;
        }
    }
    *dst = '\0';
}

int parseUrlParams(char *queryString, char *results[][2], int resultsMaxCt, boolean decodeUrl)
{
    int ct = 0;

    while (queryString && *queryString && ct < resultsMaxCt)
    {
        results[ct][0] = strsep(&queryString, "&");
        results[ct][1] = strchrnul(results[ct][0], '=');
        if (*results[ct][1])
            *results[ct][1]++ = '\0';

        if (decodeUrl)
        {
            percentDecode(results[ct][0]);
            percentDecode(results[ct][1]);
        }

        ct++;
    }

    return ct;
}

int status = WL_IDLE_STATUS;

void setup()
{ 
    Serial.begin(9600); // initialize serial communication
    pinMode(9, OUTPUT); // set the LED pin mode

        // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    
    lcd.setRGB(colorR, colorG, colorB);
    
    // Print a message to the LCD.
    lcd.print("hello, world!");
    
    // check for the WiFi module:
    if (WiFi.status() == WL_NO_MODULE)
    {
        Serial.println("Communication with WiFi module failed!");
        // don't continue
        while (true)
            ;
    }

    String fv = WiFi.firmwareVersion();
    if (fv < WIFI_FIRMWARE_LATEST_VERSION)
    {
        Serial.println("Please upgrade the firmware");
    }

    // attempt to connect to WiFi network:
    while (status != WL_CONNECTED)
    {
        Serial.print("Attempting to connect to Network named: ");
        Serial.println(ssid); // print the network name (SSID);

        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);
        // wait 10 seconds for connection:
        delay(10000);
    }
    server.begin();    // start the web server on port 80
    printWifiStatus(); // you're connected now, so print out the status
}

char url[100];

boolean done = false;

char responseCopy = "";

void loop()
{
    // set the cursor to column 0, line 1
    // (note: line 1 is the second row, since counting begins with 0):
    lcd.setCursor(0, 1);
    // print the number of seconds since reset:
    lcd.print(millis()/1000);
    WiFiClient client = server.available(); // listen for incoming clients

    char buf[100];
    char *params[5][2];

    if (client)
    {                                 // if you get a client,
        Serial.println("new client"); // print a message out the serial port
        String currentLine = "";      // make a String to hold incoming data from the client
        String httpGetUrl = "";
        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 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)
                    {
                        // 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();

                        // the content of the HTTP response follows the header:
                        // client.print("Click <a href=\"/H\">here</a> turn the LED on pin 9 on<br>");
                        client.print(webpage);

                        // 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
                }
                else
                {

                    if (currentLine.startsWith("GET /H?from="))
                    {

                        httpGetUrl += currentLine;

                        httpGetUrl.remove(0, 7);
                        int http = httpGetUrl.indexOf(" HTTP/1.1");
                        httpGetUrl.remove(http, 9);

                        httpGetUrl.toCharArray(url, 100);

                        char *tests[] = {
                            url,
                        };

                        for (int i = 0; i < sizeof(tests) / sizeof(*tests); i++)
                        {
                            Serial.print("parsing \"");
                            Serial.print(tests[i]);

                            // copy test[i] into the buffer
                            // because the parser overwrites what is i the string it is passed.
                            strcpy(buf, tests[i]);

                            // parse the buffer into params[][]
                            int resultsCt = parseUrlParams(buf, params, 5, true);

                            // print off the results;

                            Serial.print("\" produced ");
                            Serial.print(resultsCt);
                            Serial.print(" parameters:");
                            Serial.println();

                            for (int i = 0; i < resultsCt; i++)
                            {
                                Serial.print("param ");
                                Serial.print(i);
                                Serial.print(" name \"");
                                Serial.print(params[i][0]);
                                Serial.print("\", param \"");
                                Serial.print(params[i][1]);
                                Serial.print("\".");
                                Serial.println();
                            }

                            postMessage["from"] = params[0][1];
                            postMessage["to"] = params[1][1];
                            postMessage["lastOne"] = params[2][1];

                            serializeJson(postMessage, jsonBody);

                            Serial.print("Json Body: ");
                            Serial.println(jsonBody);

                            Serial.println("making POST request");

                            done = true;
                        }
                    }
                }

                // Check to see if the client request was "GET /H" or "GET /L":
                //  if (currentLine.endsWith("GET /H")) {
                while (done)
                {
                    http.post("/getDataByTrip", contentType, jsonBody);

                    // read the status code and body of the response
                    int statusCode = http.responseStatusCode();
                    String responseRequest = http.responseBody();

                    Serial.print("Status code: ");
                    Serial.println(statusCode);
                    Serial.print("Response: ");
                    Serial.println(responseRequest);

                    DeserializationError error = deserializeJson(doc, responseRequest);

                    if (error) {
                      Serial.print(F("deserializeJson() failed: "));
                      Serial.println(error.f_str());
                      return;
                    }

                    const char* from = doc["from"];
                    const char* toTrain = doc["to"];
                    int gleis = doc["gleis"];
                    int lateInMinutes = doc["lateInMinutes"];
                    const char* departure = doc["departure"];
                    int waggonsCount = doc["waggonsCount"];

                    Serial.print("To Request: ");
                    Serial.println(toTrain);

                    jsonBody = "";
               
                    
                    if (responseRequest.length() > 10)
                    {
                        done = false;
                    }
                    else
                    {

                        done = false;
                    }
                    responseRequest = "";
                }
                //}
            }
        }
        // close the connection:
        client.stop();
        Serial.println("client disconnected");
    }
}

It writes 31 bytes, that's the first ArduinoJson buffer size (32 bytes including the terminating null byte). So something goes wrong after the first buffer got written. Unfortunately ArduinoJson is a template hell, so I haven't found out, what goes wrong.

Does anything change if you declare webpage as const char instead of char?

Wow this was the problem. Thank you very much. I'm just wondering, what is the big difference between the const char and the normal char

With the atmega4809 on the UNO WiFi rev2, the compiler stores const data in flash memory instead of putting it in ram.

1 Like

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