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.