Example sketches for the new Arduino IDE for ESP8266

Moderator: igrr

User avatar
By martinayotte
#24039 Maybe there is a problem, maybe not.
But the main issue is that WebServer doesn't deal with PROGMEM anyway.
It build again a String in RAM to add header, and then pass it to sendContent() function which is in fact sending the content with multiple chunks of HTTP_DOWNLOAD_UNIT_SIZE (defined as 1460).
What we need is to have a fix in WebServer by adding a new send() and a new sendContent() functions which should deal with PROGMEM separately from the header, having the header in RAM and then sending content chucks directly from PROGMEM using memccpy_P() (defined in pgmspace.cpp) until the last chunk.
User avatar
By ridge
#24051
Makuna commented an hour ago

With Progmem, you really need to look closely at the Arduino docs, the way it was original designed is not how I would have done it, but it is the way it is in this project for compatibility.

The core of the problem is, the compiler can't tell the difference between these two variables to decide which function to call; as the PROGMEM doesn't not effect the type, it only effects where in memory the data is stored.

const char stringInFlash[] PROGMEM = "in flash";
const char stringInRam[] = "in ram";

But the memory location they are stored at have different requirements. Specifically, in flash, the data pointer must always be 32bit aligned and reads are always 32bits. But the same code reads both flash and ram. So if the code tries to read one byte at a time, it will cause an exception.

If you use the above "stringInFlash" variable in program method (end in _P), then there is an implied knowledge that the passed variable is in flash and it does the right thing in the method.
If you use the same variable to try to call a method that has versions that can take flash memory, then the variable is best defined differently so that the right method is picked by the compiler.

So, in your example, you have

server.on ("/style.css", []() {
String content(DATA_css);
server.send(server.client(), "text/css", content );
} );

since it can't tell DATA_css is in flash, you need to let it know, by casting it like this

server.on ("/style.css", []() {
String content(reinterpret_cast<const __FlashStringHelper *>(DATA_css));
server.send(server.client(), "text/css", content );
} );

This assumes you have enough RAM to temporally store the complete string.

FYI: I glanced at the Server code to see how hard it would be to convert to have a send_P(), unfortunately it is not simple; but in the long run I agree it would be interesting. As @martinayotte mentions, a good start is to separate out the header and content for sending, then the rest gets simpler.



The depth of knowledge in the open source community never ceases to amaze me....

I replaced all server.send instances in all the ESP_WebConfig_Master project files that look like:
server.send ( 200, "text/html", PAGE_WaitAndReload );

To:
server.send ( 200, "text/html", reinterpret_cast<const __FlashStringHelper *>(PAGE_WaitAndReload ));



Every thing works smooth and no crashes at all!

@Mike, I am able access both local network IP address and soft AP address at the same time.
User avatar
By Mike Bedford
#24119 Thank you all for the responses!

As for my soft AP and the client running at the same time, I took the advice of commenting out that section of code and that fixed my issue. Thanks again! I had a feeling it was simply running into the admin timeout.

As for the connection issues, I understand (to an extent) what is going on based on all the great feedback. However, I am not sure which approach to take at the moment. It seems a few people have tried a few different things and each have had success? Can someone elaborate which of the following is the best approach based on past responses?

1. Remove all PROGMEM except for:
i remove ALL PROGMEM except the one for : const char PAGE_NetworkConfiguration[] PROGMEM/**/ = R"=====(".... (the big one !) and i got the necessary heap space... and all is running OK...


2. Use the My WebConfig derived from Irriation_1 example from Proteus74 and leave it alone:
My WebConfig derived Irrigation_1 has been solid performer for at least 12 hours now. This confirms my thesis so far. The superior web coding skills of proteus74 are still intact in the Irrigation_1 example.


3. Rename server.send instances:
I replaced all server.send instances in all the ESP_WebConfig_Master project files that look like:
server.send ( 200, "text/html", PAGE_WaitAndReload );

To:
server.send ( 200, "text/html", reinterpret_cast<const __FlashStringHelper *>(PAGE_WaitAndReload ));



Every thing works smooth and no crashes at all!


Final thoughts on this before I make any changes? Which is the best approach?

Thanks!

Mike
User avatar
By ridge
#24161 WebConfig version: 1.1.3 - 2015-07-20 with the

reinterpret_cast<const __FlashStringHelper *>

modifier added as shown is working beautifully for me.


proteus74 has brought the world of web coding firmly into the embedded controller camp.
To me, this is the first solution for IoT that I am willing to put a lot of time into. It is awesome!