/ DHT_Google_Spreadsheet / google_spreadsheet.py
google_spreadsheet.py
  1  # SPDX-FileCopyrightText: 2019 Tony DiCola for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  """
  6  Google Spreadsheet DHT Sensor Data-logging Example
  7  
  8  Copyright (c) 2014 Adafruit Industries
  9  Author: Tony DiCola
 10  Modified by: Brent Rubell for Adafruit Industries
 11  
 12  Permission is hereby granted, free of charge, to any person obtaining a copy
 13  of this software and associated documentation files (the "Software"), to deal
 14  in the Software without restriction, including without limitation the rights
 15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 16  copies of the Software, and to permit persons to whom the Software is
 17  furnished to do so, subject to the following conditions:
 18  
 19  The above copyright notice and this permission notice shall be included in all
 20  copies or substantial portions of the Software.
 21  
 22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 28  SOFTWARE.
 29  """
 30  import sys
 31  import time
 32  import datetime
 33  
 34  import board
 35  import adafruit_dht
 36  import gspread
 37  from oauth2client.service_account import ServiceAccountCredentials
 38  
 39  # Type of sensor, can be `adafruit_dht.DHT11` or `adafruit_dht.DHT22`.
 40  # For the AM2302, use the `adafruit_dht.DHT22` class.
 41  DHT_TYPE = adafruit_dht.DHT22
 42  
 43  # Example of sensor connected to Raspberry Pi Pin 23
 44  DHT_PIN  = board.D4
 45  # Example of sensor connected to Beaglebone Black Pin P8_11
 46  # DHT_PIN  = 'P8_11'
 47  
 48  # Initialize the dht device, with data pin connected to:
 49  dhtDevice = DHT_TYPE(DHT_PIN)
 50  
 51  # Google Docs OAuth credential JSON file.  Note that the process for authenticating
 52  # with Google docs has changed as of ~April 2015.  You _must_ use OAuth2 to log
 53  # in and authenticate with the gspread library.  Unfortunately this process is much
 54  # more complicated than the old process.  You _must_ carefully follow the steps on
 55  # this page to create a new OAuth service in your Google developer console:
 56  #   http://gspread.readthedocs.org/en/latest/oauth2.html
 57  #
 58  # Once you've followed the steps above you should have downloaded a .json file with
 59  # your OAuth2 credentials.  This file has a name like SpreadsheetData-<gibberish>.json.
 60  # Place that file in the same directory as this python script.
 61  #
 62  # Now one last _very important_ step before updating the spreadsheet will work.
 63  # Go to your spreadsheet in Google Spreadsheet and share it to the email address
 64  # inside the 'client_email' setting in the SpreadsheetData-*.json file.  For example
 65  # if the client_email setting inside the .json file has an email address like:
 66  #   149345334675-md0qff5f0kib41meu20f7d1habos3qcu@developer.gserviceaccount.com
 67  # Then use the File -> Share... command in the spreadsheet to share it with read
 68  # and write acess to the email address above.  If you don't do this step then the
 69  # updates to the sheet will fail!
 70  GDOCS_OAUTH_JSON       = 'your SpreadsheetData-*.json file name'
 71  
 72  # Google Docs spreadsheet name.
 73  GDOCS_SPREADSHEET_NAME = 'DHT'
 74  
 75  # How long to wait (in seconds) between measurements.
 76  FREQUENCY_SECONDS      = 30
 77  
 78  
 79  def login_open_sheet(oauth_key_file, spreadsheet):
 80      """Connect to Google Docs spreadsheet and return the first worksheet."""
 81      try:
 82          scope =  ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
 83          credentials = ServiceAccountCredentials.from_json_keyfile_name(oauth_key_file, scope)
 84          gc = gspread.authorize(credentials)
 85          worksheet = gc.open(spreadsheet).sheet1 # pylint: disable=redefined-outer-name
 86          return worksheet
 87      except Exception as ex: # pylint: disable=bare-except, broad-except
 88          print('Unable to login and get spreadsheet.  Check OAuth credentials, spreadsheet name, \
 89          and make sure spreadsheet is shared to the client_email address in the OAuth .json file!')
 90          print('Google sheet login failed with error:', ex)
 91          sys.exit(1)
 92  
 93  
 94  print('Logging sensor measurements to\
 95   {0} every {1} seconds.'.format(GDOCS_SPREADSHEET_NAME, FREQUENCY_SECONDS))
 96  print('Press Ctrl-C to quit.')
 97  worksheet = None
 98  while True:
 99      # Login if necessary.
100      if worksheet is None:
101          worksheet = login_open_sheet(GDOCS_OAUTH_JSON, GDOCS_SPREADSHEET_NAME)
102  
103      # Attempt to get sensor reading.
104      temp = dhtDevice.temperature
105      humidity = dhtDevice.humidity
106  
107      # Skip to the next reading if a valid measurement couldn't be taken.
108      # This might happen if the CPU is under a lot of load and the sensor
109      # can't be reliably read (timing is critical to read the sensor).
110      if humidity is None or temp is None:
111          time.sleep(2)
112          continue
113  
114      print('Temperature: {0:0.1f} C'.format(temp))
115      print('Humidity:    {0:0.1f} %'.format(humidity))
116  
117      # Append the data in the spreadsheet, including a timestamp
118      try:
119          worksheet.append_row((datetime.datetime.now().isoformat(), temp, humidity))
120      except: # pylint: disable=bare-except, broad-except
121          # Error appending data, most likely because credentials are stale.
122          # Null out the worksheet so a login is performed at the top of the loop.
123          print('Append error, logging in again')
124          worksheet = None
125          time.sleep(FREQUENCY_SECONDS)
126          continue
127  
128      # Wait 30 seconds before continuing
129      print('Wrote a row to {0}'.format(GDOCS_SPREADSHEET_NAME))
130      time.sleep(FREQUENCY_SECONDS)