Jelajahi Sumber

Rewrote example JsonHttpClient.ino (fixes #600)

Benoit Blanchon 8 tahun lalu
induk
melakukan
126f7ab819
2 mengubah file dengan 65 tambahan dan 156 penghapusan
  1. 7 3
      CHANGELOG.md
  2. 58 153
      examples/JsonHttpClient/JsonHttpClient.ino

+ 7 - 3
CHANGELOG.md

@@ -1,6 +1,10 @@
 ArduinoJson: change log
 =======================
 
+HEAD
+----
+* Rewrote example `JsonHttpClient.ino` (issue #600)
+
 v5.11.2
 -------
 
@@ -45,20 +49,20 @@ v5.10.0
 ### BREAKING CHANGES :warning:
 
 | Old syntax                      | New syntax          |
-|---------------------------------|---------------------|
+|:--------------------------------|:--------------------|
 | `double_with_n_digits(3.14, 2)` | `3.14`              |
 | `float_with_n_digits(3.14, 2)`  | `3.14f`             |
 | `obj.set("key", 3.14, 2)`       | `obj["key"] = 3.14` |
 | `arr.add(3.14, 2)`              | `arr.add(3.14)`     |
 
 | Input     | Old output | New output |
-|-----------|------------|------------|
+|:----------|:-----------|:-----------|
 | `3.14159` | `3.14`     | `3.14159`  |
 | `42.0`    | `42.00`    | `42`       |
 | `0.0`     | `0.00`     | `0`        |
 
 | Expression                     | Old result | New result |
-|--------------------------------|------------|------------|
+|:-------------------------------|:-----------|:-----------|
 | `JsonVariant(42).is<int>()`    | `true`     | `true`     |
 | `JsonVariant(42).is<float>()`  | `false`    | `true`     |
 | `JsonVariant(42).is<double>()` | `false`    | `true`     |

+ 58 - 153
examples/JsonHttpClient/JsonHttpClient.ino

@@ -1,181 +1,86 @@
-// Sample Arduino Json Web Client
-// Downloads and parse http://jsonplaceholder.typicode.com/users/1
-//
 // ArduinoJson - arduinojson.org
 // Copyright Benoit Blanchon 2014-2017
 // MIT License
+//
+// Example of an HTTP client parsing a JSON response.
+//
+// This program perform an HTTP GET of arduinojson.org/example.json
+// Here is the expected response:
+// {
+//   "sensor": "gps",
+//   "time": 1351824120,
+//   "data": [
+//     48.756080,
+//     2.302038
+//   ]
+// }
+// See http://arduinojson.org/assistant/ to compute the size of the buffer.
+//
+// Disclaimer: the code emphasize the communication between client and server,
+// it doesn't claim to be a reference of good coding practices.
 
 #include <ArduinoJson.h>
 #include <Ethernet.h>
 #include <SPI.h>
 
-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();
-}
+  Serial.begin(9600);
+  while (!Serial);
 
-// ARDUINO entry point #2: runs over and over again forever
-void loop() {
-  if (connect(server)) {
-    if (sendRequest(server, resource) && skipResponseHeaders()) {
-      UserData userData;
-      if (readReponseContent(&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() {
+  echo("Initialize Ethernet library");
   byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
-  if (!Ethernet.begin(mac)) {
-    Serial.println("Failed to configure Ethernet");
-    return;
-  }
-  Serial.println("Ethernet ready");
+  Ethernet.begin(mac) || die("Failed to configure Ethernet");
   delay(1000);
-}
 
-// Open connection to the HTTP server
-bool connect(const char* hostName) {
-  Serial.print("Connect to ");
-  Serial.println(hostName);
+  echo("Connect to HTTP server");
+  EthernetClient client;
+  client.setTimeout(10000);
+  client.connect("arduinojson.org", 80) || die("Connection failed");
 
-  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.0");
-  client.print("Host: ");
-  client.println(host);
+  echo("Send HTTP request");
+  client.println("GET /example.json HTTP/1.0");
+  client.println("Host: arduinojson.org");
   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!");
+  client.println() || die("Failed to send request");
+
+  echo("Check HTTP status");
+  char status[32] = {0};
+  client.readBytesUntil('\r', status, sizeof(status));
+  if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
+    echo(status);
+    die("Unexpected HTTP response");
   }
 
-  return ok;
-}
-
-// 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 readReponseContent(struct UserData* userData) {
-  // Compute optimal size of the JSON buffer according to what we need to parse.
-  // See http://arduinojson.org/assistant/
-  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
-      + MAX_CONTENT_SIZE;    // additional space for strings
+  echo("Skip HTTP headers");
+  char endOfHeaders[] = "\r\n\r\n";
+  client.find(endOfHeaders) || die("Invalid response");
 
-  // Allocate a temporary memory pool
+  echo("Allocate JsonBuffer");
+  const size_t BUFFER_SIZE = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
   DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
 
+  echo("Parse JSON object");
   JsonObject& root = jsonBuffer.parseObject(client);
+  if (!root.success()) die("Parsing failed!");
 
-  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
+  echo("Extract values");
+  echo(root["sensor"].as<char*>());
+  echo(root["time"].as<char*>());
+  echo(root["data"][0].as<char*>());
+  echo(root["data"][1].as<char*>());
 
-  return true;
+  echo("Disconnect");
+  client.stop();
 }
 
-// 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);
-}
+void loop() {}
 
-// Close the connection with the HTTP server
-void disconnect() {
-  Serial.println("Disconnect");
-  client.stop();
+void echo(const char* message) {
+  Serial.println(message);
 }
 
-// Pause for a 1 minute
-void wait() {
-  Serial.println("Wait 60 seconds");
-  delay(60000);
-}
+bool die(const char* message) {
+  Serial.println(message);
+  while (true);  // loop forever
+  return false;
+}