6

I'm developing a program that uses the HTML server in the WiFi101 library.

My hardware does not have SD card storage so all source html needs to be stored as strings in the sketch at compile time. To aid in development I want to keep my html files separate from the sketch and include them at compile time.

Is there a way to use #include in the Arduino IDE and assign the included file to a string/char array constant? If so can the path to the included file be relative to the sketch's path?

Notes: Similar question on Stack overflow: https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char

Edit: There are lots of great answers here to solve this in a more robust fashion. The correct thing to do is setup a proper build system. If I were to set this up I'd be temped to try something like Gulp since you could easily minify/lint your web content. As this is a small project I ended up just running the HTML through a minifier service and copy/pasted into strings.

Geordie
  • 195
  • 1
  • 7

4 Answers4

5

I found another way to include a literal file (html, css, or other) and assign it to a constant string without resorting to make files:

Add one line of code on top of your html (css, js, etc) file, and another at the bottom, and save it with an extra .h extension. Then include that file in de Arduino IDE. This could easily be done by a (manually executed) script, every time those files are changed.

const char *indexHtml = R"====( // added by script
<html> <!-- original .html file -->
.
.
.
</html> <!-- end .html -->
)===="; // added by script

The variable name can be derived from the original filename. The result is saved with an extra .h extension. In the .ino (or .cpp) you can then include this file:

#include index.html.h

This will compile in the Arduino IDE.

marc
  • 51
  • 1
  • 2
1

C++ has 'raw string literals'. You can put a constant string, without escaping special characters, into the source code between an opening and closing 'tag'. You can choose the tag to be something that is not in the raw string. In following example the tag is =====.

const char* s1 = R"=====(Hello
"World")=====";

is same as

const char* s2 = "Hello\n\"World\"";

This way you can put your large strings into separate .h files and include them. On AVR use PROGMEM to save RAM.

Juraj
  • 18,264
  • 4
  • 31
  • 49
1

This will probably not work with the Arduino IDE. If you are willing to go through a Makefile-based workflow, you can install this generic Arduino Makefile, which should make things easier.

With that Makefile installed in /usr/share/arduino/Arduino.mk, the following test worked on an Arduino Uno. It is based on the objcopy trick from the article Embedding of binary data into programs.

Project's Makefile:

BOARD_TAG    = uno
MONITOR_PORT = /dev/ttyACM0
OTHER_OBJS   = text.o

include /usr/share/arduino/Arduino.mk

text.o: text.txt
    avr-objcopy -I binary -O elf32-avr -B avr:5 $< $@

text.txt:

Hello, World!

include-blob.ino

extern "C" const uint8_t _binary_text_txt_start[];
extern "C" const uint8_t _binary_text_txt_size;

void setup() {
    Serial.begin(9600);
    Serial.write(_binary_text_txt_start, (size_t) &_binary_text_txt_size);
}

void loop(){}

The program just prints “Hello, World!”, but if you modify text.txt and retype make, it will print whatever you had in this file. Please note that the text is not NUL-terminated, so you have to use the _binary_*_size symbol to know its size.

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81
0

An easy way to do this is to write a C program to convert your files that you want included into your source into a form that looks like:

byte file_001[] = { 0x00, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0A,
                    0x01, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C,

                    ...

                    0x03, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C };

The converted file can contain binary data without issue instead of just ASCII.

You can then access the file directly using: file_001[index]

Jeff Wahaus
  • 583
  • 2
  • 5