diff --git a/CHANGELOG.md b/CHANGELOG.md index be842280..ff6c5ea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ HEAD ---- * Added `JsonVariant::as()` as a synonym for `JsonVariant::as()` (issue #257) +* Added example `JsonHttpClient` (issue #256) v5.1.1 ------ diff --git a/examples/JsonHttpClient/JsonHttpClient.ino b/examples/JsonHttpClient/JsonHttpClient.ino new file mode 100644 index 00000000..b0ed4710 --- /dev/null +++ b/examples/JsonHttpClient/JsonHttpClient.ino @@ -0,0 +1,195 @@ +// Sample Arduino Json Web Client +// Downloads and parse http://jsonplaceholder.typicode.com/users/1 +// +// Copyright Benoit Blanchon 2014-2016 +// MIT License +// +// Arduino JSON library +// https://github.com/bblanchon/ArduinoJson +// If you like this project, please add a star! + +#include +#include +#include + +EthernetClient client; + +const char* server = "jsonplaceholder.typicode.com"; // server's address +const char* resource = "/users/1"; // http resource +const unsigned long BAUD_RATE = 9600; // serial connection speed +const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server +const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response + +// The type of data that we want to extract from the page +struct UserData { + char name[32]; + char company[32]; +}; + +// ARDUINO entry point #1: runs once when you press reset or power the board +void setup() { + initSerial(); + initEthernet(); +} + +// ARDUINO entry point #2: runs over and over again forever +void loop() { + if (connect(server)) { + if (sendRequest(server, resource) && skipResponseHeaders()) { + char response[MAX_CONTENT_SIZE]; + readReponseContent(response, sizeof(response)); + + UserData userData; + if (parseUserData(response, &userData)) { + printUserData(&userData); + } + } + disconnect(); + } + wait(); +} + +// Initialize Serial port +void initSerial() { + Serial.begin(BAUD_RATE); + while (!Serial) { + ; // wait for serial port to initialize + } + Serial.println("Serial ready"); +} + +// Initialize Ethernet library +void initEthernet() { + byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; + if (!Ethernet.begin(mac)) { + Serial.println("Failed to configure Ethernet"); + return; + } + Serial.println("Ethernet ready"); + delay(1000); +} + +// Open connection to the HTTP server +bool connect(const char* hostName) { + Serial.print("Connect to "); + Serial.println(hostName); + + bool ok = client.connect(hostName, 80); + + Serial.println(ok ? "Connected" : "Connection Failed!"); + return ok; +} + +// Send the HTTP GET request to the server +bool sendRequest(const char* host, const char* resource) { + Serial.print("GET "); + Serial.println(resource); + + client.print("GET "); + client.print(resource); + client.println(" HTTP/1.1"); + client.print("Host: "); + client.println(server); + client.println("Connection: close"); + client.println(); + + return true; +} + +// Skip HTTP headers so that we are at the beginning of the response's body +bool skipResponseHeaders() { + // HTTP headers end with an empty line + char endOfHeaders[] = "\r\n\r\n"; + + client.setTimeout(HTTP_TIMEOUT); + bool ok = client.find(endOfHeaders); + + if (!ok) { + Serial.println("No response or invalid response!"); + } + + return ok; +} + +// Read the body of the response from the HTTP server +void readReponseContent(char* content, size_t maxSize) { + size_t length = client.readBytes(content, maxSize); + content[length] = 0; + Serial.println(content); +} + +// Parse the JSON from the input string and extract the interesting values +// Here is the JSON we need to parse +// { +// "id": 1, +// "name": "Leanne Graham", +// "username": "Bret", +// "email": "Sincere@april.biz", +// "address": { +// "street": "Kulas Light", +// "suite": "Apt. 556", +// "city": "Gwenborough", +// "zipcode": "92998-3874", +// "geo": { +// "lat": "-37.3159", +// "lng": "81.1496" +// } +// }, +// "phone": "1-770-736-8031 x56442", +// "website": "hildegard.org", +// "company": { +// "name": "Romaguera-Crona", +// "catchPhrase": "Multi-layered client-server neural-net", +// "bs": "harness real-time e-markets" +// } +// } +bool parseUserData(char* content, struct UserData* userData) { + // Compute optimal size of the JSON buffer according to what we need to parse. + // This is only required if you use StaticJsonBuffer. + const size_t BUFFER_SIZE = + JSON_OBJECT_SIZE(8) // the root object has 8 elements + + JSON_OBJECT_SIZE(5) // the "address" object has 5 elements + + JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements + + JSON_OBJECT_SIZE(3); // the "company" object has 3 elements + + // Allocate a temporary memory pool on the stack + StaticJsonBuffer jsonBuffer; + // If the memory pool is too big for the stack, use this instead: + // DynamicJsonBuffer jsonBuffer; + + JsonObject& root = jsonBuffer.parseObject(content); + + if (!root.success()) { + Serial.println("JSON parsing failed!"); + return false; + } + + // Here were copy the strings we're interested in + strcpy(userData->name, root["name"]); + strcpy(userData->company, root["company"]["name"]); + // It's not mandatory to make a copy, you could just use the pointers + // Since, they are pointing inside the "content" buffer, so you need to make + // sure it's still in memory when you read the string + + return true; +} + +// Print the data extracted from the JSON +void printUserData(const struct UserData* userData) { + Serial.print("Name = "); + Serial.println(userData->name); + Serial.print("Company = "); + Serial.println(userData->company); +} + +// Close the connection with the HTTP server +void disconnect() { + Serial.println("Disconnect"); + client.stop(); +} + +// Pause for a 1 minute +void wait() { + Serial.println("Wait 60 seconds"); + delay(60000); +} diff --git a/scripts/travis/arduino.sh b/scripts/travis/arduino.sh index 085aa9e2..4de24c15 100755 --- a/scripts/travis/arduino.sh +++ b/scripts/travis/arduino.sh @@ -11,5 +11,6 @@ export PATH=$PATH:/tmp/arduino/ ln -s $PWD /tmp/arduino/libraries/ArduinoJson -arduino --verify --board $BOARD $PWD/examples/JsonParserExample/JsonParserExample.ino -arduino --verify --board $BOARD $PWD/examples/JsonGeneratorExample/JsonGeneratorExample.ino +for EXAMPLE in $PWD/examples/*/*.ino; do + arduino --verify --board $BOARD $EXAMPLE +done