Last active
December 20, 2016 05:47
-
-
Save mdrovdahl/782380781fd4c2bdad902efa46ded68d to your computer and use it in GitHub Desktop.
Rough access to SinopeTech Smart Thermostat Data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# This is a rough prototype for accessing device information from Sinope devices via their neviweb.com service and recording it to a Google Sheet | |
# TODO | |
# 1. move neviweb u/p into google auth json file in home directory | |
# 2. add outside temperature, avaliable from neviweb, but ideally from Bloomsky Weather Station | |
# 3. run as recurring cron job | |
from __future__ import print_function | |
import httplib2 | |
import os | |
import sys,requests, datetime | |
from apiclient import discovery | |
from oauth2client import client | |
from oauth2client import tools | |
from oauth2client.file import Storage | |
try: | |
import argparse | |
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() | |
except ImportError: | |
flags = None | |
# Google API configuration | |
# If modifying these scopes, delete your previously saved credentials | |
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json | |
SCOPES = 'https://www.googleapis.com/auth/spreadsheets' | |
CLIENT_SECRET_FILE = 'client_secret.json' | |
APPLICATION_NAME = 'neviweb cli' | |
# Neviweb configuration | |
EMAIL = "[email protected]" # Replace with your neviweb account login e-mail | |
PASSWORD = "secret" # Replace with your neviweb account login password | |
GATEWAYNAME = 'Home' # Replace with the name of your neviweb network | |
DATASERVER = "https://neviweb.com/" | |
def neviweb_login(): | |
path = 'api/login' | |
payload = {'email': EMAIL, 'password': PASSWORD, 'stayConnected': '0'} | |
r = requests.post(DATASERVER+path, data=payload) | |
session = r.json() | |
# TODO To check that a request is successful, use r.raise_for_status() or check r.status_code is what you expect. | |
if "session" in session: | |
session_token = {'Session-Id': session['session']} | |
else: | |
sys.exit("error: no neviweb session token") | |
return (session_token) | |
def neviweb_get_gateways(neviweb_session): | |
path = 'api/gateway' | |
r = requests.get(DATASERVER+path, headers=neviweb_session) | |
# TODO To check that a request is successful, use r.raise_for_status() or check r.status_code is what you expect. | |
gateways = r.json() | |
return (gateways) | |
def neviweb_get_devices(neviweb_session,neviweb_gateway): | |
path = 'api/device' | |
if "id" in neviweb_gateway: | |
payload = {'gatewayId': neviweb_gateway['id']} | |
else: | |
sys.exit("errro: no gatewayID") | |
r = requests.get(DATASERVER+path, headers=neviweb_session, params=payload) | |
# TODO To check that a request is successful, use r.raise_for_status() or check r.status_code is what you expect. | |
devices = r.json() | |
return (devices) | |
def cToF(temp): | |
#TODO make a generic formatTemp(temp,format) function | |
return (str((9.0/5.0*float(temp)+32))) | |
def neviweb_read_device(neviweb_session,neviweb_device): | |
path = 'api/device/'+str(neviweb_device['id'])+'/data?force=1' | |
r = requests.get(DATASERVER+path, headers=neviweb_session) | |
# TODO if not data returned, throw an error | |
return (r.json()) | |
def google_get_credentials(): | |
"""Gets valid Google user credentials from storage. | |
If nothing has been stored, or if the stored credentials are invalid, | |
the OAuth2 flow is completed to obtain the new credentials. | |
Returns: | |
Credentials, the obtained credential. | |
""" | |
home_dir = os.path.expanduser('~') | |
credential_dir = os.path.join(home_dir, '.credentials') | |
if not os.path.exists(credential_dir): | |
os.makedirs(credential_dir) | |
credential_path = os.path.join(credential_dir, | |
'sheets.googleapis.com-python-quickstart.json') | |
store = Storage(credential_path) | |
credentials = store.get() | |
if not credentials or credentials.invalid: | |
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) | |
flow.user_agent = APPLICATION_NAME | |
if flags: | |
credentials = tools.run_flow(flow, store, flags) | |
else: # Needed only for compatibility with Python 2.6 | |
credentials = tools.run(flow, store) | |
print('Storing credentials to ' + credential_path) | |
return credentials | |
def writeData(data): | |
""" | |
Creates a Google Sheets API service object and logs device readings into this Google Sheet: | |
https://docs.google.com/spreadsheets/d/1Zf7rbuSXqeaoNPT-b3eVHDcSo8q7B86xCqk7gUeol3Y/edit | |
""" | |
""" | |
Specify the Google Sheet ID and rangeName | |
""" | |
spreadsheetId = '1Zf7rbuSXqeaoNPT-b3eVHDcSo8q7B86xCqk7gUeol3Y' | |
rangeName = 'Sheet1!A1:A5' | |
""" | |
Authorize the API request | |
""" | |
googleCredentials = google_get_credentials() | |
""" | |
Build the API request and create the service object | |
""" | |
http = googleCredentials.authorize(httplib2.Http()) | |
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?' | |
'version=v4') | |
service = discovery.build('sheets', 'v4', http=http, | |
discoveryServiceUrl=discoveryUrl) | |
""" | |
Write data to spreadsheet | |
""" | |
result = service.spreadsheets().values().append(spreadsheetId = spreadsheetId,range=rangeName,valueInputOption='RAW',body=data).execute() | |
""" | |
TODO: do something with the result to ensure the write worked | |
""" | |
def main(): | |
""" | |
Program description goes here. | |
TODO: add Try Except clauses for each of these function calls | |
""" | |
""" | |
Creates a neviweb.com session | |
""" | |
neviweb_session = neviweb_login() | |
""" | |
Loop through gateways. Untested with > one gateway | |
""" | |
neviweb_gateways = neviweb_get_gateways(neviweb_session) | |
for neviweb_gateway in neviweb_gateways: | |
gatewayName = str(neviweb_gateway['name']) | |
""" | |
Loop through devices. Tested with up to five | |
""" | |
neviweb_devices = neviweb_get_devices(neviweb_session,neviweb_gateway) | |
for neviweb_device in neviweb_devices: | |
""" | |
Gather some device data: name, temperature, setpoint | |
""" | |
deviceData = neviweb_read_device(neviweb_session,neviweb_device) | |
deviceName = str(neviweb_device['name']) | |
deviceTempF = float(cToF(deviceData['temperature'])) | |
deviceSetpoint = float(cToF(deviceData['setpoint'])) | |
""" | |
Prepare a payload for writing to Google sheets | |
""" | |
data = {'values': [[gatewayName, deviceName, deviceTempF, deviceSetpoint, str(datetime.datetime.now())]]} | |
""" | |
Write the device data to Google sheets | |
""" | |
writeData(data) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment