I’ll show you how to use Mongoose, the most popular open-source embedded web server and networking library (see our GitHub page), with any ARM board supported by the ARM mbed
(see list) attached to a TI CC3100 WiFi daughterboard.
All you need to do is to connect the CC3100 board to your device with 6 wires. Connect the 4 SPI lines to respective pins for SPI port 1. For the nHIB and IRQ lines you can pick any available GPIO. You can easily find the SPI_MOSI
, SPI_MISO
, SPI_CLK
, and SPI_CS
on the board with the help of this picture:
Here's a pin out diagram of the STM64 so you don't have to search it yourself:
The mbed
platform defines the main SPI to be:
SPI_MOSI = PB_15,
SPI_MISO = PB_14,
SPI_SCK = PD_3,
SPI_CS = PH_6,
That would be SPI2 technically. Probably because SPI1 is used to drive the LCD screen.
Just connect the wires with the same name, i.e. SPI_MOSI
on the STM32 connects to the SPI_MOSI
on the CC3100 (no crossing input/out; MOSI stands for master output slave input).
The goal of this project is to build have a device that connects to a WiFi network and hosts an HTTP server. The device will run some custom code in reaction to incoming requests, e.g. blink a LED and generate some reply.
I simplified a bit the source I'm presenting here; just to avoid distractions. You can find the source code for a dynamic web server example here.
int main() {
// configures network interface
SimpleLinkInterface wifi(PG_10, PG_11); // nHIB, IRQ pins
// disables default example web server
sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID);
// connect to your wifi network
wifi.connect("yourssid", "yourpass");
// ...
Awesome. The call to wifi.connect
call will block until the device joins the network and obtains an IP address and is thus ready to operate.
We can access the IP address and other info about the WiFi connection:
const char *ip = wifi.get_ip_address();
const char *gw = wifi.get_gateway();
const char *mac = wifi.get_mac_address();
printf("IP address is: %s\n", ip ? ip : "No IP");
printf("GW address is: %s\n", gw ? gw : "No IP");
printf("MAC address is: %s\n", mac ? mac : "No MAC");
Or we can start a dynamic web server, to serve your device's APIs:
mg_connection *nc = mg_bind(&mgr, "80", ev_handler);
mg_set_protocol_http_websocket(nc);
printf("Server address: http://%s\n", ip);
This will start a web server on the default http
port and you can write code that reacts to HTTP request. Let's see how:
void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
switch (ev) {
case MG_EV_ACCEPT: {
// ...
break;
}
case MG_EV_HTTP_REQUEST: {
struct http_message *hm = (struct http_message *) ev_data;
mg_send_response_line(nc, 200,
"Content-Type: text/html\r\n"
"Connection: close");
mg_printf(nc,
"\r\n<h1>Hello, Sir!</h1>\r\n"
"You asked for %.*s\r\n",
(int) hm->uri.len, hm->uri.p);
// we're done with the reply.
nc->flags |= MG_F_SEND_AND_CLOSE;
// Make something happen on the device
led_blue = !led_blue;
break;
}
case MG_EV_CLOSE: {
// ...
break;
}
}
}
Use your browser to navigate to the URL that gets printed out on the serial console. You should see a simple greeting page, created by the MG_EV_HTTP_REQUEST
handler and the corresponding messages:
0x20000878: Connection from 192.168.1.15:38548
0x20000708: GET /
0x20000708: Connection closed
ConclusionAs you can see, mongoose uses an event based programming model. It allows Mongoose to be very efficient and that matters a lot on very small devices.
Ever wondered how can your brand new home ADSL router be so slow to render that HTML-from-the-90s admin page of his? Simple: it doesn't use Mongoose. And there is more, there are many supported protocols, but the good old http
server never dies.
You can learn more about Mongoose by reading the doc.
Comments