Save Data to Kintone with an ESP8266

Contents

Overview

This article introduces how to save data to a Kintone App using a NodeMCU ESP8266 (External link) 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.

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
tips
Note

Before proceeding with the integration, it's advisable to set up and test it in a controlled testing environment.
Apply for a free Kintone Developer License through this link.

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.

Download and install the Arduino IDE (External link) . After installation, open the IDE to the first sketch.

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

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

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

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.

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.

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.

caution
Attention

Connecting via a faulty or weak USB cable is the most common reason for failure to connect. Refer to the official Arduino Help Article (External link) 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 (External link) 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
tips
Note

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 (External link) 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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#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.

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

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.

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

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 (External link) 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.

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.

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

caution
Attention

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

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

Enter the data specified in this article's 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.