Save Data to Kintone with an ESP8266
Tags: arduino, iot, restapi, kintone
Published: 2023-08-31 06:43:09

### Overview

This article introduces how to save data to a Kintone App using a [NodeMCU ESP8266](https://www.make-it.ca/nodemcu-details-specifications/) device.

While the device used in this tutorial is an ESP8266, the concepts apply to most if not all Arduino devices with Wi-Fi capabilities. And similarly, while the Web Database used in this tutorial is [Kintone](https://kintone.dev/en/), changing the contents of the HTTP Request allows for any REST API based web database to be used.

Video available as well:

{% youtube xtEetrzM_8c %}



### General Flow

The general flow of this tutorial is as follows:

1. Connect and Test the ESP8266
2. Create a Kintone App to store data
3. Write and upload a program or "sketch" to the device that will access Kintone's [REST API](/docs/kintone/rest-api/)

### Initial Setup

First connect the ESP8266 to your computer via USB cable. Note that the quality of cable matters, and a high quality USB cable should be used, or else the cable will only provide power and will fail to transfer data.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m95xqrijilg9pgp0jdfj.png)

Download and install the [Arduino IDE](https://www.arduino.cc/en/software). After installation, open the IDE to the first sketch.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zva13jgw59p04v59u461.png)

Open the settings menu, and in the `Additional Boards Manager URLs` option, add the following open source ESP8266 repository URL: `https://arduino.esp8266.com/stable/package_esp8266com_index.json`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/op35s71e0w3uta54bs87.png)

This will allow support for various Arduino and other micro-controller devices based on the ESP8266 chip to be downloaded.

Next, open the library tab on the left side of the IDE, and search for `ESP8266`. Install the latest version.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgc4vkzz22oaessu2e5p.png)

Next, ensure that the ESP8266 is connected via USB cable, and in the top menu, select the ESP8266 model to use. If it is not displayed automatically, click on the `Select Other Board and Port` menu item.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dlyzm12y0bv99oz03krm.png)

Search for ESP8266, and select the model that is being used. In this example, a LoLin board based on NodeMCU is used. This will vary depending on the development board used. Select the port the ESP8266 is connected to.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p9ik9ih68265767qa9hq.png)

Common port names are `usbserial`, `usbmodem`, `COM3`, or other names that end with `(USB)`, but will depend on the operating system, drivers, and firmware of the development environment.


> Connecting via a faulty or weak USB cable is the most common reason for failure to connect. Refer to the official [Arduino Help Article](https://support.arduino.cc/hc/en-us/articles/4412955149586-If-your-board-does-not-appear-on-a-port-in-Arduino-IDE) for more troubleshooting.

After confirming the board is connected, the ESP8266 is ready for development.

### Create a Kintone App
#### Set up the Fields

For this example, a simple App with a single **Radio button** field will be used.
Create a new App with the following field settings.

| Field Type | Field Name | Field Code | Remarks |
| :-- | :-- | :-- | :-- |
| Radio button | Favorite Color | color | Options: Red, Blue, Green, Yellow |

Additional fields will not significantly increase the complexity of this tutorial, and only require the JSON object sent via the ESP8266 be modified accordingly (with some exceptions, such as **Attachment** fields and **Tables**.)

#### Create an API Token

Create an API Token with `View records` and `Add records` permissions.
Refer to the [Generating API Tokens](https://get.kintone.help/k/en/id/040471.html) article on the Kintone Help site for more information on API Tokens.

#### Information For Later

The following information will be used to test the POST request from the ESP8266.

1. API Token
2. Subdomain (for example.kintone.com, the subdomain is `example`)
3. App ID

> The App ID can be found in the URL of the App.
> For example, if the URL of the App is `https://example.kintone.com/k/23/`, the App ID is **23**.

### Program a POST request in the ESP8266

The ESP8266 is a popular choice for low-cost IOT, as it has Wi-Fi capabilities, and is able to connect to and broadcast Wi-Fi networks. The code in this example has three main goals:

1. Connect to a Wi-Fi network, and start a server on the local network.
2. Create HTML routes and a form
3. Pass the information from the form to a REST API request to Kintone.

This tutorial can be downloaded from the [Kintone Workshop](https://github.com/kintone-workshops/esp8266-sketches/blob/c823a31ee1e81ca56def025de43af2584246ae16/1_kintone_web_server/kintone_web_server.ino) repository.
In this example the user needs only to edit the code regarding Wi-Fi credentials on lines 8 and 9, before compiling and uploading the code to the ESP8266.

#### Complete Code Example

``` dart
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>

// Your WIFI information. You must be connected to the same WIFI network to connect via localhost.
const char* ssid = "MY_WIFI_SSID";
const char* password = "MY_WIFI_PASSWORD";
// A JSON Class to handle JSON data.
DynamicJsonDocument doc(1024);
// The ESP8266 server class.
ESP8266WebServer server(80);
// A variable for tracking a valid HTTP response or not.
bool result = false;

// The setup function is special, and runs only once.
void setup() {
  // The BAUD rate for the serial monitor.
  Serial.begin(9600);
  delay(100);
  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");
  Serial.println(WiFi.localIP());

  // The HTTP server class let's developers create routes, that run specific functions on access.
  // Here, we designate the root route, the /post route, and a 404 route.
  server.on("/", handle_OnConnect);
  server.on("/post", handlePost);
  server.onNotFound(handle_NotFound);
  server.begin();
  Serial.println("HTTP server started");
}

// The loop function. This will run continuously, and let our server class handle incoming requests.
void loop() {
  server.handleClient();
}

// This function runs when users access the root route.
void handle_OnConnect() {
  Serial.println("Welcome. Enter your App ID, API Key, and Subdomain to post some data.");
  // This function sends a 200 on successful connection, and then runs the SendHTML() function.
  server.send(200, "text/html", SendHTML());
}

// This function runs after clicking the Post to Kintone button, and the users accesses the /post route.
void handlePost() {
  // A new HTTP Client.
  WiFiClientSecure client;
  HTTPClient http;
  client.setInsecure();
  Serial.println("Attempting to Save to Kintone...");
  // The variables passed to this route via Form Action. The user's subdomain, appID, API Token, and favorite color.
  String subdomain = server.arg("subdomain");
  String appID = server.arg("appID");
  String token = server.arg("API");
  String color = server.arg("color");
  // The URL for our HTTP Request.
  String URL = "https://" + subdomain + ".kintone.com/k/v1/record.json?app=" + appID;
  Serial.print("info:");
  Serial.println(URL);
  http.begin(client, URL);
  // Formatting the POST Request JSON Object.
  doc["app"] = appID;
  JsonObject recordObject = doc.createNestedObject("record");
  recordObject["color"]["value"] = color;
  String json;
  serializeJson(doc, json);
  // End of JSON formatting. The JSON string is saved to the json variable.

  // Response Code variable for our HTTP request.
  int responseCode = 0;
  // Adding request headers via the http class.
  http.addHeader("X-Cybozu-API-Token", token);
  http.addHeader("Content-type", "application/json");
  // Making the POST request, and saving the result to responseCode
  responseCode = http.POST(json);
  Serial.printf("http Response Code = %d \n", responseCode);
  String payload = http.getString();
  Serial.println(payload);

  // Using an IF statement we can choose which HTML to send for each response code. Details are logged to the serial monitor.
  if (responseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(responseCode);
    String payload = http.getString();
    Serial.println(payload);
    result = true;
  } else if (responseCode == 400) {
    Serial.print("Error code: ");
    Serial.println(responseCode);
    result = false;
  }
  else {
    Serial.print("Error code: ");
    Serial.println(responseCode);
    result = false;
  }
  // Ending the HTTP request, and passing the result variable to the PostResult function.
  http.end();
  server.send(200, "text/html", PostResult(result));
}

// A function to handle all 404 routes.
void handle_NotFound() {
  server.send(404, "text/plain", "Not found");
}

// A Function which returns an html string. This is the HTML which gets displayed on each route. SendHTML for the root route.
// Note that quotation marks (" ") within HTML must be escaped with a forward slash ( \ ).
String SendHTML() {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Kintone and IOT!</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<h1>ESP8266 Web Server</h1>\n";
  ptr += "<p>Enter your subdomain, appID, and API Token!</p>";
  ptr += "<form action=\"/post\">";
  ptr += "<label for=\"subdomain\">Subdomain:</label><input type=\"text\" id=\"subdomain\" name=\"subdomain\" value=\"example\">";
  ptr += "<label for=\"appID\">App ID:</label><input type=\"text\" id=\"appID\" name=\"appID\" value=\"1\"/>";
  ptr += "<label for=\"API\">API Token:</label><input type=\"text\" id=\"API\" name=\"API\" value=\"1J22qNAR54I4eiMcd0JmfDAavJNfNJDVaqt34X9A\"/><br>";
  ptr += "<label for=\"color\">Pick your favorite Color:</label><br>";
  ptr += "<label for=\"red\">Red</label>";
  ptr += "<input type=\"radio\" id=\"red\" name=\"color\" value=\"Red\" checked /><br>";
  ptr += "<label for=\"blue\">Blue</label>";
  ptr += "<input type=\"radio\" id=\"blue\" name=\"color\" value=\"Blue\" /><br>";
  ptr += "<label for=\"green\">Green</label>";
  ptr += "<input type=\"radio\" id=\"green\" name=\"color\" value=\"Green\" /><br>";
  ptr += "<label for=\"yellow\">Yellow</label>";
  ptr += "<input type=\"radio\" id=\"yellow\" name=\"color\" value=\"Yellow\" /><br>";
  ptr += "<input type=\"submit\" value=\"Post to Kintone!\">";
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}

// This function displays the HTML for the /post route. It takes a boolean variable, which can be used to alter the HTML displayed.
String PostResult(uint8_t result) {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Kintone and IOT!</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<h1>ESP8266 Web Server</h1>\n";
  ptr += "<p>Post page</p>";
  if (result) {
    ptr += "<p>Success!</p>";
  } else {
    ptr += "<p>Error Posting Check your JSON, API Token, and field codes!</p>";
  }
  ptr += "<a href='/'> Go Back </a>";
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}
```

#### Compile and Upload the code

After copying and pasting the code example into the Arduino IDE, the validity of the code can be checked via the `Verify` button.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p3eclxj4u5hu5ska446p.png)

Any errors will be output in the `output` console in the bottom of the editor.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sx64z3h3kun5tvaxqyj.png)

If the code is technically sound, it can then be uploaded to the ESP8266.
Ensure that the ESP8266 is still connected via USB, and click on the `Upload` button in the top menu.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zwq0zhfxb9ofxbjbehh.png)

Upload progress and any errors can be confirmed in the `output` console in the bottom tab of the Arduino IDE.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddst485bqxpbd26jo6fk.png)

### Test the Sample Code

Once the code is uploaded, information on how to connect to the ESP8266 will be displayed in the `serial monitor`.

#### Displaying the Serial Monitor

The `serial monitor` is a fundamental concept of micro-controller development. For more information, refer to the [Using the Serial Monitor tool](https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-serial-monitor) article in the Arduino documentation.

In this example, the serial monitor is used in the code via `Serial.println()` statements. Those familiar with web development will find it similar to the JavaScript `console.log()` function. The Serial Monitor can be displayed in the bottom on the Arduino IDE.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ce22xybmph7tomgtmba2.png)

Developers may noticed erroneous characters appearing in the Serial Monitor. When starting transmissions, a display of a few garbled characters is common and not a cause for concern. If no characters are displayed in the `serial monitor`, ensure that the baud rate matches the baud rate specified in the code.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3fpoi2axlgnrgsz99ti.png)

The IP address on the local network is displayed in the `serial monitor`.

> Ensure that the ESP8266, and the computer that will display the ESP8266 web page are connected to the same Wi-Fi network.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15pn2p4hfpgac2d0j65v.png)

Accessing the IP Address of the ESP8266 will lead to the root route being executed in code, and displaying the following HTML:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eyxzw25g4q6e3zgkdq7b.png)

Enter the data specified in this article's [Information For Later](#information-for-later) section, choose a color, and click on the `Post to Kintone!` button.
Check the Kintone App to see if a new record has been successfully posted.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgish8ladtnox371xgj9.png)