├── Advanced
├── README.md
└── ESP8266-example_button-press.cpp
├── ESP8266-example.cpp
├── GoogleScripts-example.gs
└── README.md
/Advanced/README.md:
--------------------------------------------------------------------------------
1 | # Advanced Examples
2 |
3 | ###### This folder contains additional examples for interfacing with Google Sheets. These assumes you have followed the instructions for the main tutorial and are able to successfully send data to Google Sheets.
4 |
5 | ### Example 1: Log data on button press
6 |
7 | This example will log data to Google Sheets when a button is pressed.
8 |
9 | 1. Wire a push button so that pin D1 will read HIGH when the button is pressed.
10 |
11 | Example wiring diagram: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Button
12 |
13 | 2. Follow the instructions for the main tutorial, but use the code from the "ESP8266-example_button-press.cpp" file for the ESP8266 instead.
14 | 3. Data will be published to Google Sheets when the button is pressed.
15 |
16 | *Notes:*
17 |
18 | If data is not being sent to Google Sheets on a regular interval but rather on an event trigger (such as only sending data when a button is pressed), occasionally the first attempt to send data will fail due to an issue with the way Google Sheets handles the request. The data is sent if a second attempt is made shortly after the first. Therefore, the example code is set up to automatically try again if the first attempt fails.
19 |
20 |
21 |
22 |
23 | ### Example 2: Send values from Google Sheets to the ESP8266
24 |
25 | To send multiple values from Google Sheets back to the ESP8266, you can create an array in the Google Script code that contains variables and the values assigned to them:
26 | ```
27 | var return_json = {
28 | 'return_value_1': sheet.getRange('A1').getValue(),
29 | 'return_value_2': sheet.getRange('B1').getValue(),
30 | 'return_value_3': sheet.getRange('C1').getValue()
31 | };
32 | ```
33 | This creates the variables return_value_1, return_value_2, and return_value_3, and assignes them the values contained in cells A1, B1, and C1. Note that there is no comma after the last variable.
34 |
35 | Then, in place of ```return ContentService.createTextOutput(str);``` (which returns the str variable back to the ESP8266), replace it with:
36 | ```
37 | return ContentService.createTextOutput(JSON.stringify(return_json)).setMimeType(ContentService.MimeType.JSON);
38 | ```
39 | This converts the array to a JSON string and returns it back to the ESP8266.
40 |
41 | Now that the JSON string has been sent back to the ESP8266, use the [ArduinoJson library](https://arduinojson.org/) to deserialize the JSON string and assign the values to variables in the ESP8266 code.
42 |
43 | It is recommended to use the [ArduinoJson Assistant](https://arduinojson.org/v6/assistant/) to create the example code. In Step 1 of the assistant, choose the Processor as ESP8266, the Mode as Deserialize, and the Input Type as String. In the next step, enter the JSON string that is being sent to the ESP8266. For the above example if we assume the values 1, 2 and 3 are entered in cells A1, B1 and C1, the string sent to the ESP8266 would be ```{"return_value_1":1,"return_value_2":2,"return_value_3":3}```. Going through the next steps will create the code required for the ESP8266 to take the values sent from Google Sheets and save them as variables in the ESP8266 code.
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ESP8266-example.cpp:
--------------------------------------------------------------------------------
1 | // Example Arduino/ESP8266 code to upload data to Google Sheets
2 | // Follow setup instructions found here:
3 | // https://github.com/StorageB/Google-Sheets-Logging
4 | //
5 | // email: StorageUnitB@gmail.com
6 |
7 |
8 | #include
9 | #include
10 | #include "HTTPSRedirect.h"
11 |
12 | // Enter network credentials:
13 | const char* ssid = "network";
14 | const char* password = "password";
15 |
16 | // Enter Google Script Deployment ID:
17 | const char *GScriptId = "AKfycpwCtWuN3BNIO5CR9BtZJAMaRNUgusldcAz6V7rtGCg1L5srZ5iAEZumVeb-1ea5Y6mg3Q";
18 |
19 | // Enter command (insert_row or append_row) and your Google Sheets sheet name (default is Sheet1):
20 | String payload_base = "{\"command\": \"insert_row\", \"sheet_name\": \"Sheet1\", \"values\": ";
21 | String payload = "";
22 |
23 | // Google Sheets setup (do not edit)
24 | const char* host = "script.google.com";
25 | const int httpsPort = 443;
26 | const char* fingerprint = "";
27 | String url = String("/macros/s/") + GScriptId + "/exec";
28 | HTTPSRedirect* client = nullptr;
29 |
30 | // Declare variables that will be published to Google Sheets
31 | int value0 = 0;
32 | int value1 = 0;
33 | int value2 = 0;
34 |
35 | void setup() {
36 |
37 | Serial.begin(9600);
38 | delay(10);
39 | Serial.println('\n');
40 |
41 | // Connect to WiFi
42 | WiFi.begin(ssid, password);
43 | Serial.print("Connecting to ");
44 | Serial.print(ssid); Serial.println(" ...");
45 |
46 | while (WiFi.status() != WL_CONNECTED) {
47 | delay(1000);
48 | Serial.print(".");
49 | }
50 | Serial.println('\n');
51 | Serial.println("Connection established!");
52 | Serial.print("IP address:\t");
53 | Serial.println(WiFi.localIP());
54 |
55 | // Use HTTPSRedirect class to create a new TLS connection
56 | client = new HTTPSRedirect(httpsPort);
57 | client->setInsecure();
58 | client->setPrintResponseBody(true);
59 | client->setContentTypeHeader("application/json");
60 |
61 | Serial.print("Connecting to ");
62 | Serial.println(host);
63 |
64 | // Try to connect for a maximum of 5 times
65 | bool flag = false;
66 | for (int i=0; i<5; i++){
67 | int retval = client->connect(host, httpsPort);
68 | if (retval == 1){
69 | flag = true;
70 | Serial.println("Connected");
71 | break;
72 | }
73 | else
74 | Serial.println("Connection failed. Retrying...");
75 | }
76 | if (!flag){
77 | Serial.print("Could not connect to server: ");
78 | Serial.println(host);
79 | return;
80 | }
81 | delete client; // delete HTTPSRedirect object
82 | client = nullptr; // delete HTTPSRedirect object
83 | }
84 |
85 |
86 | void loop() {
87 |
88 | // create some fake data to publish
89 | value0 ++;
90 | value1 = random(0,1000);
91 | value2 = random(0,100000);
92 |
93 |
94 | static bool flag = false;
95 | if (!flag){
96 | client = new HTTPSRedirect(httpsPort);
97 | client->setInsecure();
98 | flag = true;
99 | client->setPrintResponseBody(true);
100 | client->setContentTypeHeader("application/json");
101 | }
102 | if (client != nullptr){
103 | if (!client->connected()){
104 | client->connect(host, httpsPort);
105 | }
106 | }
107 | else{
108 | Serial.println("Error creating client object!");
109 | }
110 |
111 | // Create json object string to send to Google Sheets
112 | payload = payload_base + "\"" + value0 + "," + value1 + "," + value2 + "\"}";
113 |
114 | // Publish data to Google Sheets
115 | Serial.println("Publishing data...");
116 | Serial.println(payload);
117 | if(client->POST(url, host, payload)){
118 | // do stuff here if publish was successful
119 | }
120 | else{
121 | // do stuff here if publish was not successful
122 | Serial.println("Error while connecting");
123 | }
124 |
125 | // a delay of several seconds is required before publishing again
126 | delay(5000);
127 | }
128 |
--------------------------------------------------------------------------------
/GoogleScripts-example.gs:
--------------------------------------------------------------------------------
1 | // Example Google Scrips code to upload data to Google Sheets from Arduino/ESP8266
2 | // Follow setup instructions found here:
3 | // https://github.com/StorageB/Google-Sheets-Logging
4 | //
5 | // email: StorageUnitB@gmail.com
6 |
7 |
8 | // Enter Spreadsheet ID here
9 | var SS = SpreadsheetApp.openById('3213k-okfjdk-gkeJHjd87-vdKei-lKQDIc-a2a_Hjg4');
10 | var str = "";
11 |
12 |
13 | function doPost(e) {
14 |
15 | var parsedData;
16 | var result = {};
17 |
18 | try {
19 | parsedData = JSON.parse(e.postData.contents);
20 | }
21 | catch(f){
22 | return ContentService.createTextOutput("Error in parsing request body: " + f.message);
23 | }
24 |
25 | if (parsedData !== undefined){
26 | var flag = parsedData.format;
27 | if (flag === undefined){
28 | flag = 0;
29 | }
30 |
31 | var sheet = SS.getSheetByName(parsedData.sheet_name); // sheet name to publish data to is specified in Arduino code
32 | var dataArr = parsedData.values.split(","); // creates an array of the values to publish
33 |
34 | // Default time zone is America/Chicago. Update time zone below with appropriate ID from here: https://developers.google.com/google-ads/api/data/codes-formats#timezone-ids
35 | var date_now = Utilities.formatDate(new Date(), "America/Chicago", "yyyy/MM/dd"); // gets the current date
36 | var time_now = Utilities.formatDate(new Date(), "America/Chicago", "hh:mm:ss a"); // gets the current time
37 |
38 | var value0 = dataArr [0]; // value0 from Arduino code
39 | var value1 = dataArr [1]; // value1 from Arduino code
40 | var value2 = dataArr [2]; // value2 from Arduino code
41 |
42 |
43 | // read and execute command from the "payload_base" string specified in Arduino code
44 | switch (parsedData.command) {
45 |
46 | case "insert_row":
47 |
48 | sheet.insertRows(2); // insert full row directly below header text
49 |
50 | //var range = sheet.getRange("A2:D2"); // use this to insert cells just above the existing data instead of inserting an entire row
51 | //range.insertCells(SpreadsheetApp.Dimension.ROWS); // use this to insert cells just above the existing data instead of inserting an entire row
52 |
53 | sheet.getRange('A2').setValue(date_now); // publish current date to cell A2
54 | sheet.getRange('B2').setValue(time_now); // publish current time to cell B2
55 | sheet.getRange('C2').setValue(value0); // publish value0 from Arduino code to cell C2
56 | sheet.getRange('D2').setValue(value1); // publish value1 from Arduino code to cell D2
57 | sheet.getRange('E2').setValue(value2); // publish value2 from Arduino code to cell E2
58 |
59 | str = "Success"; // string to return back to Arduino serial console
60 | SpreadsheetApp.flush();
61 | break;
62 |
63 | case "append_row":
64 |
65 | var publish_array = new Array(); // create a new array
66 |
67 | publish_array [0] = date_now; // add current date to position 0 in publish_array
68 | publish_array [1] = time_now; // add current time to position 1 in publish_array
69 | publish_array [2] = value0; // add value0 from Arduino code to position 2 in publish_array
70 | publish_array [3] = value1; // add value1 from Arduino code to position 3 in publish_array
71 | publish_array [4] = value2; // add value2 from Arduino code to position 4 in publish_array
72 |
73 | sheet.appendRow(publish_array); // publish data in publish_array after the last row of data in the sheet
74 |
75 | str = "Success"; // string to return back to Arduino serial console
76 | SpreadsheetApp.flush();
77 | break;
78 |
79 | }
80 |
81 | return ContentService.createTextOutput(str);
82 | } // endif (parsedData !== undefined)
83 |
84 | else {
85 | return ContentService.createTextOutput("Error! Request body empty or in incorrect format.");
86 | }
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/Advanced/ESP8266-example_button-press.cpp:
--------------------------------------------------------------------------------
1 | // Example Arduino/ESP8266 code to upload data to Google Sheets when a button is pressed
2 | // Follow setup instructions found here:
3 | // https://github.com/StorageB/Google-Sheets-Logging
4 | // reddit: u/StorageB107
5 | // email: StorageUnitB@gmail.com
6 |
7 |
8 | #include
9 | #include
10 | #include "HTTPSRedirect.h"
11 |
12 | // Enter network credentials:
13 | const char* ssid = "network";
14 | const char* password = "password";
15 |
16 | // Enter Google Script Deployment ID:
17 | const char *GScriptId = "AKfycpwCtWuN3BNIO5CR9BtZJAMaRNUgusldcAz6V7rtGCg1L5srZ5iAEZumVeb-1ea5Y6mg3Q";
18 |
19 | // Enter command (insert_row or append_row) and your Google Sheets sheet name (default is Sheet1):
20 | String payload_base = "{\"command\": \"insert_row\", \"sheet_name\": \"Sheet1\", \"values\": ";
21 | String payload = "";
22 |
23 | // Google Sheets setup (do not edit)
24 | const char* host = "script.google.com";
25 | const int httpsPort = 443;
26 | const char* fingerprint = "";
27 | String url = String("/macros/s/") + GScriptId + "/exec";
28 | HTTPSRedirect* client = nullptr;
29 |
30 | // Declare variables that will be published to Google Sheets
31 | int value0 = 0;
32 | int value1 = 0;
33 | int value2 = 0;
34 |
35 | // Declare variables that will keep track of whether or not the data has been published
36 | bool data_published = false;
37 | int error_count = 0;
38 |
39 | void setup() {
40 |
41 | Serial.begin(9600);
42 | delay(10);
43 | Serial.println('\n');
44 |
45 | // Declare pin D1 as a button input:
46 | pinMode(D1, INPUT);
47 |
48 | // Connect to WiFi
49 | WiFi.begin(ssid, password);
50 | Serial.print("Connecting to ");
51 | Serial.print(ssid); Serial.println(" ...");
52 |
53 | while (WiFi.status() != WL_CONNECTED) {
54 | delay(1000);
55 | Serial.print(".");
56 | }
57 | Serial.println('\n');
58 | Serial.println("Connection established!");
59 | Serial.print("IP address:\t");
60 | Serial.println(WiFi.localIP());
61 |
62 | // Use HTTPSRedirect class to create a new TLS connection
63 | client = new HTTPSRedirect(httpsPort);
64 | client->setInsecure();
65 | client->setPrintResponseBody(true);
66 | client->setContentTypeHeader("application/json");
67 |
68 | Serial.print("Connecting to ");
69 | Serial.println(host);
70 |
71 | // Try to connect for a maximum of 5 times
72 | bool flag = false;
73 | for (int i=0; i<5; i++){
74 | int retval = client->connect(host, httpsPort);
75 | if (retval == 1){
76 | flag = true;
77 | Serial.println("Connected");
78 | break;
79 | }
80 | else
81 | Serial.println("Connection failed. Retrying...");
82 | }
83 | if (!flag){
84 | Serial.print("Could not connect to server: ");
85 | Serial.println(host);
86 | return;
87 | }
88 | delete client; // delete HTTPSRedirect object
89 | client = nullptr; // delete HTTPSRedirect object
90 | }
91 |
92 |
93 | void loop() {
94 |
95 | // attempt to publish to Google Sheets when button is pressed (when pin reads HIGH)
96 | if (digitalRead(D1) == HIGH) {
97 |
98 | // before attempting to publish to Google Sheets, set the data_published variable to false and error_count to 0
99 | data_published = false;
100 | error_count = 0;
101 |
102 | // create some fake data to publish
103 | value0 ++;
104 | value1 = random(0,1000);
105 | value2 = random(0,100000);
106 |
107 | // the while loop will attempt to publish data up to 3 times
108 | while(data_published == false && error_count < 3){
109 |
110 | static bool flag = false;
111 | if (!flag){
112 | client = new HTTPSRedirect(httpsPort);
113 | client->setInsecure();
114 | flag = true;
115 | client->setPrintResponseBody(true);
116 | client->setContentTypeHeader("application/json");
117 | }
118 | if (client != nullptr){
119 | if (!client->connected()){
120 | client->connect(host, httpsPort);
121 | }
122 | }
123 | else{
124 | Serial.println("Error creating client object!");
125 | }
126 |
127 | // Create json object string to send to Google Sheets
128 | payload = payload_base + "\"" + value0 + "," + value1 + "," + value2 + "\"}";
129 |
130 | // Publish data to Google Sheets
131 | Serial.println("Publishing data...");
132 | Serial.println(payload);
133 |
134 | if(client->POST(url, host, payload)){
135 | // do stuff here if publish was successful
136 | data_published = true;
137 | }
138 | else{
139 | // do stuff here if publish was not successful
140 | Serial.println("Error while connecting");
141 | error_count++;
142 | delay(2000);
143 | }
144 | yield();
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Log data from an ESP8266 to Google Sheets
2 |
3 | Below are step by step instructions to begin logging data using an ESP8266 module without the need for a third party service. This will publish random number values, so no additional hardware or sensors are required for the script to run.
4 |
5 |
6 |
7 | ## Instructions for Google Sheets
8 |
9 | 1. Create new Google Sheets document, and give it a name.
10 |
11 | 2. Type the following text into each of the following cells:
12 |
13 | - Cell A1: `Date`
14 | - Cell B1: `Time`
15 | - Cell C1: `value0`
16 | - Cell D1: `value1`
17 | - Cell E1: `value2`
18 |
19 |
20 | 
21 |
22 |
23 | 3. Get the Spreadsheet ID from the URL.
24 |
25 | For example, if the URL is:
26 |
27 | https://docs.google.com/spreadsheets/d/1sqp9hIM5VvDGEf8i9H-W1Z72lm0O5-ZxC16sMMS-cgo/edit#gid=0
28 |
29 | Then the Spreadsheet ID is:
30 |
31 | 1sqp9hIM5VvDGEf8i9H-W1Z72lm0O5-ZxC16sMMS-cgo
32 |
33 | 
34 |
35 |
36 | 4. From the Google Sheets menu, go to `Extensions > Apps Script`
37 |
38 | 5. Delete all of the default text in the script editor, and paste the GoogleScripts-example.gs code.
39 |
40 | 6. Update the Spreadsheet ID (line 9) with the ID obtained in step 3, and click `Save`.
41 |
42 | *Note: The Spreadsheet ID must be contained in single quotation marks as shown in the example code, and **the script must be saved before continuing** to the next step.*
43 |
44 | 8. Click the blue `Deploy` button at the top right of the page, and select `New Deployment`.
45 |
46 | Click the `gear` icon next to Select Type, and select `Web App` and modify the following:
47 |
48 | - Enter a Description (optional)
49 | - Execute as: `Me`
50 | - Who has access: `Anyone` *(note: do not select `Anyone with a Google Account` - you must scroll down to the bottom to find `Anyone`)*
51 |
52 | Click `Deploy`
53 |
54 | 9. Click `Authorize access` then select your Google account.
55 |
56 | On the "Google hasn't verified this app" screen, select `Advanced` > `Go to Untitled project (unsafe)` > `Allow`
57 |
58 | Copy and save the `Deployment ID` for use in the ESP8266 code, and click `Done`.
59 |
60 | 10. From the script editor, click `Save` and then `Run`.
61 |
62 | *Note: Nothing will happen when you click run but you must do that once before continuing.*
63 |
64 |
65 |
66 |
67 |
68 | ## Instructions for ESP8266
69 |
70 | 1. In the Arduino IDE, paste the "ESP8266-example.cpp" code into a blank sketch. Overwrite any existing code that was there.
71 |
72 | 2. Update the following info:
73 |
74 | - Add your Wifi network name
75 | - Add your Wifi password
76 | - Replace the Google Script Deployment ID with the ID obtained in step 8 above
77 |
78 | *Note: The Deployment ID must be contained in quotation marks as shown in the example code. The Deployment ID can also be found by clicking `Deploy > Manage Deployments`.*
79 |
80 | 3. Install the HTTPSRedirect library from here:
81 |
82 | https://github.com/electronicsguy/HTTPSRedirect
83 |
84 | - Click on the green "code" button and "Download ZIP"
85 | - Unzip the file and move the HTTPSRedirect folder to your library directory
86 |
87 | *Note: For Arduino IDE 2.0 and above, the library directory is a subfolder named "libraries" at the path shown under File > Preferences > Sketchbook location. Create the "libraries" folder if it does not already exist (do not capitalize the L in the "libraries" folder name)*
88 |
89 | 4. Delete the config.cpp file from the HTTPSRedirect folder.
90 |
91 | *Note: It must be deleted, not just renamed as it may cause errors when compiling the sketch.*
92 |
93 | 5. Upload code to your ESP8266 module and watch data get published to your sheet!
94 |
95 |
96 | ## Important Note
97 |
98 | When making changes to the Google Scripts code, you will need to click `Save` then `Deploy > New deployment` for any new changes to take effect. You will be given a new Deployment ID that you will have to update in the ESP8266 code each time (each new deployment is given a new Deployment ID).
99 |
100 |
101 |
102 | ## Troubleshooting
103 |
104 | 1. If you get a "Something went wrong. Please try again." error message from Google during step 9 when trying to authorize access, try using the Google Chorme browser for this step. I have found that Google has blocked access from some other browsers.
105 | 2. If you get an error when compiling, go to the HTTPSRedirect library folder and verify that you have deleted the "config.cpp" file. Note that the network ID, password, host, and Google Script Deployment ID are defined in the main ESP8266 example code and therefore this file is not required and may cause errors for some compilers.
106 | 3. If you are unable to get this working for your existing project, it is recommended that you start with a brand new empty project and spreadsheet and then follow the above instructions. Once you have the example above working, then make the changes to implement your own custom code.
107 | 4. For applications where data is not sent on a regular interval but rather on an event trigger (such as only sending data when a button is pressed), occasionally the first attempt to send data will fail. Therefore, the code must be modified to send the data again if the first attempt fails. See the example under the "Advanced" folder for additional information.
108 | 5. This tutorial does not work for an ESP32 device.
109 |
110 |
111 | #### I hope you found this tutorial helpful!
112 |
113 |
114 |
--------------------------------------------------------------------------------