Bonnie Eisenman bio photo

Bonnie Eisenman

Software engineer, author, knitter, Esperantist. Member of NYC Resistor and author of Learning React Native.
Email me: bonnie.eisenman@gmail.com.

Twitter Github

Last week I taught a DIY Internet of Things class at NYC Resistor. We used the Adafruit Feather HUZZAH board, which has an ESP8266 WiFi chip. I hadn’t worked with this chip before. Turns out, it’s pretty great!

I also grabbed an OLED FeatherWing. Possibly the cutest screen I’ve ever worked with. OMG so tiny.

Anyway, once I had it all assembled the first step was to test out the WiFi. Adafruit provides some example code. Here’s the code, abbreviated:

const char* ssid     = "yourssid";
const char* password = "yourpassword";

const char* host = "wifitest.adafruit.com";
String url = "/testwifi/index.html";

void setup() {
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    }    
}

void loop() {
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
        return;
    }

    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");

    while(client.available()){
        String line = client.readStringUntil('\r');
        Serial.print(line);
    }

    delay(2000);
}  

This is a much lower-level API than I expected! I really did not anticipate having to hand-craft artisinal HTTP messages.

For the class project, I wanted students to build an alarm clock, using a web API to fetch the current time. www.timeapi.org provides a super-duper-simple API that does just that.

$ curl www.timeapi.org/est/now
2016-09-13T10:07:15-05:00

However, at first, when I tried sending a GET request from the Feather to the above URL, it…didn’t work. I got a 403 Rejected.

Hmm. That’s odd. I took another look at the request I was sending:

> GET /est/now HTTP/1.1
> Host: www.timeapi.org
> 

I double-checked it against curl:

$ curl -v www.timeapi.org/est/now
*   Trying 23.23.105.22...
* Connected to www.timeapi.org (23.23.105.22) port 80 (#0)
> GET /est/now HTTP/1.1
> Host: www.timeapi.org
> User-Agent: curl/7.43.0
> Accept: */*
> 

There are only two lines that differ:

> User-Agent: curl/7.43.0
> Accept: */*

Oh, derp. The example code doesn’t include a User-Agent string. This is fine for the wifitest page that Adafruit has set up, but won’t work for most actual sites.

So, I just modified the sketch to send the User-Agent as curl/7.43.0. Because User-Agent strings are nonsense anyway, right? And laziness is a virtue, etc, etc…

client.println(String("GET ") + url + " HTTP/1.1");
client.print("Host: ");
client.println("www.timeapi.org");
client.println("User-Agent: curl/7.43.0");
client.println();

Lo and behold, now it works.

That was really the main hurdle - otherwise, working with the Feather HUZZAH was surprisingly easy. Now I need to actually finish a project with it. ;)

The full sketch, along with other code samples from the class, is available on github.