├── Advanced ├── ESP8266-example_button-press.cpp └── README.md ├── ESP8266-example.cpp ├── GoogleScripts-example.gs └── README.md /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | ![Selection_004](https://user-images.githubusercontent.com/44729718/115277764-46881380-a10a-11eb-9be4-b6fbe7ea7091.png) 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 | ![Selection_006-3](https://user-images.githubusercontent.com/44729718/115287377-d1bad680-a115-11eb-8730-4c6ae00184a7.png) 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 | Buy Me A Coffee 114 | --------------------------------------------------------------------------------