Skip to content
Giorgioggì edited this page Jan 15, 2021 · 9 revisions

To start out with Webbino, open the SimpleServer example. It will show you how to serve a single static webpage which it is the simplest usage you can make of this library. Advanced features will be added on the top of this, so it is crucial that you understand every line of this example. Let's analyze it one line at a time. Don't worry, it is easier than it looks!

#include <Webbino.h>

You are probably used to lines like this one, as every library will have at least one. It just "brings in" the library and will need to be put at the top of every sketch where you want to use Webbino.

// Instantiate the WebServer and page storage
WebServer webserver;
FlashStorage flashStorage;

Here we declare two objects: the first one will let you interact with the actual webserver component in your code, while the second one is the Content Storage of choice, that is where the web pages (and all the rest of the content you want to make available) will reside. Webbino allows you to store your content in different places, it's up to you to choose the one that is better suited to your application:

  • Here we use the FlashStorage, which basically embeds the content inside the sketch. This is nice, as you won't have to waste a huge SD card for a few simple pages, but at the same time the content will occupy space inside your flash (remember this is only 32 kB on an Arduino Uno!), limiting the size of your code. It is a good choice when all you have to serve is a few small files. To learn how to convert HTML and other files so that they can be used with this Storage, please have a look at this page.
  • If you have to serve many files, the SdStorage is probably a better idea: after all you already have an SD slot on your Ethernet Shield, so why not make use of it?
  • If you are using an ESP8266 or ESP32, you also have another choice: these microcontrollers usually have so large flash memories (4 MB!) that it would be very hard to fill them all with code, so they can also host a filesystem where you can put any files you want. The LittleFS Storage will then help you serve those files with Webbino.
// Instantiate the network interface defined in the Webbino headers
#if defined (WEBBINO_USE_ENC28J60)
	#include <WebbinoInterfaces/ENC28J60.h>
	NetworkInterfaceENC28J60 netint;

	#define MAC_ADDRESS 0x00,0x11,0x22,0x33,0x44,0x55

	// Ethernet Slave Select pin
	const byte ETH_SS_PIN = SS;
#elif defined (WEBBINO_USE_WIZ5100) || defined (WEBBINO_USE_WIZ5500) || \
	  defined (WEBBINO_USE_ENC28J60_UIP) || defined (WEBBINO_USE_TEENSY41_NATIVE)
	#include <WebbinoInterfaces/WIZ5x00.h>
	NetworkInterfaceWIZ5x00 netint;

	#define MAC_ADDRESS 0x00,0x11,0x22,0x33,0x44,0x55

	// This is ignored for Teensy 4.1
	const byte ETH_SS_PIN = SS;
#elif defined (WEBBINO_USE_ESP8266)
	#include <WebbinoInterfaces/AllWiFi.h>

	#include <SoftwareSerial.h>
	SoftwareSerial espSerial (6, 7);

	// Wi-Fi parameters
	#define WIFI_SSID        "ssid"
	#define WIFI_PASSWORD    "password"

	NetworkInterfaceWiFi netint;
#elif defined (WEBBINO_USE_WIFI) || defined (WEBBINO_USE_WIFI101) || \
	  defined (WEBBINO_USE_ESP8266_STANDALONE)
	#include <WebbinoInterfaces/AllWiFi.h>

	// Wi-Fi parameters
	#define WIFI_SSID        "ssid"
	#define WIFI_PASSWORD    "password"

	NetworkInterfaceWiFi netint;
#elif defined (WEBBINO_USE_FISHINO)
	#include <WebbinoInterfaces/FishinoIntf.h>

	// Wi-Fi parameters
	#define WIFI_SSID        "ssid"
	#define WIFI_PASSWORD    "password"

	FishinoInterface netint;
#elif defined (WEBBINO_USE_DIGIFI)
	#include <WebbinoInterfaces/DigiFi.h>
	NetworkInterfaceDigiFi netint;
#endif

I'm sure this section has scared many people away from Webbino, but it is there to give you a very exciting possibility, which is the ability to move the same sketch from a supported platform to another: suppose you start developing for an Arduino Uno with an Ethernet shield. Then you decide you want to go wireless and move to an ESP8266: these lines will allow you to do that without a single change in your sketch! Well, I lied a bit there: you can copy this section as-is to a new sketch, but you will have to make a few changes to be honest, as different platforms require different parameters. For instance, if you are using a WiFi board, you will need to set the network SSID and password, the Ethernet shield needs a MAC address and a CS pin, etc. If you look closely, this section is divided in several sub-sections, one per supported platform, and you will only have to customize the parameters for the one for the platform you are using. After this section has been executed, an object named netint will be created, which Webbino will use to interact with the network interface of the platform you are using.

At this point you might ask: Where do I choose the platform I want to use? Good question, the answer is here.

/******************************************************************************
 * DEFINITION OF PAGES                                                        *
 ******************************************************************************/

#include "html.h"

const Page page01 PROGMEM = {index_html_name, index_html, index_html_len};
const Page page02 PROGMEM = {logo_gif_name, logo_gif, logo_gif_len};

const Page* const pages[] PROGMEM = {
	&page01,
	&page02,
	NULL
};

This is just what the content conversion script produced, copied verbatim into the sketch.

/******************************************************************************
 * MAIN STUFF                                                                 *
 ******************************************************************************/

void setup () {
	Serial.begin (115200);
	while (!Serial)
		;

	Serial.println (F("Webbino " WEBBINO_VERSION));

	Serial.println (F("Trying to get an IP address through DHCP"));

We have finally got to the setup() function! It starts initializing the serial port and using it to output a few messages.

#if defined (WEBBINO_USE_ENC28J60) || defined (WEBBINO_USE_WIZ5100) || \
	defined (WEBBINO_USE_WIZ5500) || defined (WEBBINO_USE_ENC28J60_UIP)
	byte mac[6] = {MAC_ADDRESS};
	bool ok = netint.begin (mac, ETH_SS_PIN);
#elif defined (WEBBINO_USE_TEENSY41_NATIVE)
	byte mac[6] = {MAC_ADDRESS};
	bool ok = netint.begin (mac);
#elif defined (WEBBINO_USE_ESP8266)
	espSerial.begin (9600);
	bool ok = netint.begin (espSerial, WIFI_SSID, WIFI_PASSWORD);
#elif defined (WEBBINO_USE_WIFI) || defined (WEBBINO_USE_WIFI101) || \
	  defined (WEBBINO_USE_ESP8266_STANDALONE) || defined (WEBBINO_USE_FISHINO)
	bool ok = netint.begin (WIFI_SSID, WIFI_PASSWORD);
#elif defined (WEBBINO_USE_DIGIFI)
	bool ok = netint.begin ();
#endif

Another scary section that resembles the one above. This calls the initialization method on the netint object that was created above, passing the parameters that were defined in the preceding scary section and storing the result in the ok variable: if the network interface was initialized correctly, this will be true otherwise it will be false. The good news: there's no need to touch anything in here, just copy as-is in your sketch!

	if (!ok) {
		Serial.println (F("Failed to get configuration from DHCP"));
		while (42)
			;
	} else {
		Serial.println (F("DHCP configuration done:"));
		Serial.print (F("- IP: "));
		Serial.println (netint.getIP ());
		Serial.print (F("- Netmask: "));
		Serial.println (netint.getNetmask ());
		Serial.print (F("- Default Gateway: "));
		Serial.println (netint.getGateway ());

Here we tell the user about the result of the initialization of the network interface. If it failed, we'll block forever (42 is the answer to life, the universe and everything and that includes How long is forever?), since there's some problem that needs to be solved before we can do anything (No WiFi coverage? Your cat played too much with your Ethernet cable?).

		webserver.begin (netint);

Since the network interface was initialized correctly, we can finally initialize the webserver too, handing over the network interface object.

		flashStorage.begin (pages);

This is the initialization of the content storage: FlashStorage requires the "handle" produced by the conversion script.

		webserver.addStorage (flashStorage);

Here we tell the webserver what content storage to use. Very simple. And we're done with the setup() function!

	}
}

void loop () {
	webserver.loop ();
}

At last, we need to call the webserver loop() method at every iteration of the main loop() function.

Woo-hoo, wasn't that simple? I really hope so. I'd recommend spending some time on this page, until everything is clear. At that point, taking advantage of the advanced features will be a breeze!