From bd42497a4ee86c00dc45c933afa60dddb00aa0a9 Mon Sep 17 00:00:00 2001 From: Kyle Wooten Date: Sat, 15 Jul 2017 09:26:49 -0400 Subject: [PATCH] Added occupancy checks, as well as weather checks to automatically set hvac mode to heat or cool --- ecobee/data/ecobee_authentication.json | 3 -- ecobee/data/ecobee_secret.json | 3 ++ ecobee/ecobee.py | 19 ++++++-- hydrogen/cache/occupancy.cache | 1 + hydrogen/hydrogen.py | 6 +-- main.py | 60 ++++++++++++++++++++++---- version.txt | 3 ++ wunderground/__init__.py | 0 wunderground/config/config.ini | 20 +++++++++ wunderground/wunderground.py | 47 ++++++++++++++++++++ 10 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 hydrogen/cache/occupancy.cache create mode 100644 version.txt create mode 100644 wunderground/__init__.py create mode 100644 wunderground/config/config.ini create mode 100644 wunderground/wunderground.py diff --git a/ecobee/data/ecobee_authentication.json b/ecobee/data/ecobee_authentication.json index b162790..e69de29 100644 --- a/ecobee/data/ecobee_authentication.json +++ b/ecobee/data/ecobee_authentication.json @@ -1,3 +0,0 @@ -{ - "apikey": "" -} \ No newline at end of file diff --git a/ecobee/data/ecobee_secret.json b/ecobee/data/ecobee_secret.json index e69de29..b162790 100644 --- a/ecobee/data/ecobee_secret.json +++ b/ecobee/data/ecobee_secret.json @@ -0,0 +1,3 @@ +{ + "apikey": "" +} \ No newline at end of file diff --git a/ecobee/ecobee.py b/ecobee/ecobee.py index 3a3a1c6..a87bf2c 100644 --- a/ecobee/ecobee.py +++ b/ecobee/ecobee.py @@ -2,7 +2,7 @@ import requests import logging -logging.basicConfig(filename='log/hydrogen.log', level=logging.DEBUG) +logging.basicConfig(filename='log/hydrogen.log', level=logging.INFO) with open('ecobee/data/ecobee_secret.json') as data_file: data = json.load(data_file) @@ -62,6 +62,7 @@ def get_thermostats(): '"includeSensors":"true",' '"includeProgram":"true",' '"includeEquipmentStatus":"true",' + '"includeWeather":"true",' '"includeEvents":"true",' '"includeSettings":"true"}}')} request = requests.get(url, headers=header, params=params) @@ -110,7 +111,19 @@ def get_weather(index): header = {'Content-Type': 'application/json;charset=UTF-8', 'Authorization': 'Bearer ' + accesstoken} params = {'format': 'json'} body = ('{"selection":{"selectionType":"thermostats","selectionMatch":' - '"' + thermostats[index]['identifier'] + - '"},"thermostat":{"weatherforecast":{"temperature":"}}}') + '"' + thermostats[index] + + '"},"thermostat":{"weather":{"forecast":"}}}') request = requests.post(url, headers=header, params=params, data=body) print request.json() + + +def get_remote_sensors(index): + ''' Return remote sensors based on index ''' + thermostats = get_thermostats() + return thermostats[index]['remoteSensors'] + + +def get_current_climate_setting(index): + ''' Return sleep, away, or home ''' + thermostats = get_thermostats() + return thermostats[index]['program']['currentClimateRef'] diff --git a/hydrogen/cache/occupancy.cache b/hydrogen/cache/occupancy.cache new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/hydrogen/cache/occupancy.cache @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/hydrogen/hydrogen.py b/hydrogen/hydrogen.py index 3e68ae1..afb5e54 100644 --- a/hydrogen/hydrogen.py +++ b/hydrogen/hydrogen.py @@ -49,12 +49,12 @@ def check_gmail(): service = discovery.build('gmail', 'v1', http=http) today = str(datetime.date.today()) yesterday = str(datetime.date.fromordinal(datetime.date.today().toordinal() - 1)) - todayhours = int(datetime.datetime.now().strftime("%H")) #Hour of the day in 24 hour format + todayhours = int(datetime.datetime.now().strftime("%H")) # Hour of the day in 24 hour format - if todayhours not in range(14, 19): #Check if it is peak hours for CobbEMC + if todayhours not in range(14, 19): # Check if it is peak hours for CobbEMC return 2 - #Check Gmail messages with label 41(CobbEMC Peak Hours) + # Check Gmail messages with label 41(CobbEMC Peak Hours) messages = service.users().messages().list(userId='me', labelIds='Label_41').execute().get('messages', []) for message in messages: tdata = service.users().messages().get(userId='me', id=message['id']).execute() diff --git a/main.py b/main.py index 4e7483b..a013d20 100644 --- a/main.py +++ b/main.py @@ -5,31 +5,73 @@ from ecobee import ecobee from hydrogen import hydrogen +from wunderground import wunderground logging.basicConfig(filename='log/hydrogen.log', level=logging.DEBUG) -now = datetime.datetime.now() -logging.info("Hydrogen ran at " + str(now)) # Set your ecobee index list thermostatlist = [0, 1] def main(): + now = datetime.datetime.now() + logging.info("Hydrogen ran at " + str(now)) + + """ Check for occupancy and act accordingly """ + program = ecobee.get_current_climate_setting(1) + occupancy = ecobee.get_remote_sensors(0)[1]['capability'][2]['value'] # Check if someone is home via proximity + if program == "sleep": + logging.info("Ecobee is reporting sleep program, setting result to 2") + result = 2 + elif program != "sleep": + occupancy = ecobee.get_remote_sensors(0)[1]['capability'][2]['value'] # Check if someone is home via proximity + if occupancy == "true": + with open('hydrogen/cache/occupancy.cache', 'w') as outfile: + outfile.write("0") + logging.info("Someone is home, setting result to 2") + result = 2 + elif occupancy == "false": + with open('hydrogen/cache/occupancy.cache', 'r') as infile: + occupancyint = infile.read() + with open('hydrogen/cache/occupancy.cache', 'w') as outfile: + occupancyint += 1 + outfile.write(occupancyint) + with open('hydrogen/cache/occupancy.cache', 'r') as infile: + occupancyint = infile.read() + if occupancyint >= 5: + logging.log("Looks like nobody is home, turning to off hvac mode to save power") + result = 4 + elif occupancyint <= 4: + result = hydrogen.check_gmail() + + """ Check for results of test and act accordingly """ """ Result of 1 means that the ecobees need to be turned off to avoid peak hours """ - result = hydrogen.check_gmail() - if result == 1: + if result == 1: # Peak hours! logging.info("Gmail check has come back with peak hours, setting ecobees to off hvac mode") for i in thermostatlist: requesthvacset = ecobee.set_hvac_mode(i, 'off') if requesthvacset.status_code == requests.codes.ok: logging.info("Successfully set thermostat index " + str(i) + " to off hvac mode") - elif result == 2: - logging.info("It's not peak hours right now, setting ecobees to cool") + elif result == 2: # Someone is home or asleep, and/or not peak hours + ctemp = wunderground.get_current_temperature() + if ctemp >= 66: + hvacmode = 'cool' + elif ctemp <= 65: + hvacmode = 'heat' + + if occupancy == "false": + logging.info("It's not peak hours right now, setting ecobees to " + hvacmode) + for i in thermostatlist: - requesthvacset = ecobee.set_hvac_mode(i, 'cool') + requesthvacset = ecobee.set_hvac_mode(i, hvacmode) if requesthvacset.status_code == requests.codes.ok: - logging.info("Successfully set thermostat index " + str(i) + " to cool hvac mode") - elif result == 0: + logging.info("Successfully set thermostat index " + str(i) + " to " + hvacmode + " hvac mode") + elif result == 4: # Nobody is home + for i in thermostatlist: + requesthvacset = ecobee.set_hvac_mode(i, 'off') + if requesthvacset.status_code == requests.codes.ok: + logging.info("Successfully set thermostat index " + str(i) + " to off hvac mode") + elif result == 0: # Not peak hours logging.info("No Peak Hours have been set by CobbEMC, we're good!") sys.exit(0) diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..05c4535 --- /dev/null +++ b/version.txt @@ -0,0 +1,3 @@ +Current version 0.1 + +0.1 *) @Cryson, Initial version release diff --git a/wunderground/__init__.py b/wunderground/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wunderground/config/config.ini b/wunderground/config/config.ini new file mode 100644 index 0000000..4275602 --- /dev/null +++ b/wunderground/config/config.ini @@ -0,0 +1,20 @@ +# +# INI file for weather settings. Modify this file to change weather output +# +# Example INI file +# +# user_apiid: 83jd324asjc0f5a +# user_city: New_York +# user_state: NY +# cachefile: /opt/test/Scripts/weather.data +# + +[weather_settings] +#APIID/Key from weatherunderground +user_apiid: + +#City, e.g. New_York +user_city: + +#State e.g. MN, FL, CA +user_state: diff --git a/wunderground/wunderground.py b/wunderground/wunderground.py new file mode 100644 index 0000000..c8c609d --- /dev/null +++ b/wunderground/wunderground.py @@ -0,0 +1,47 @@ +import json +import urllib2 +import ConfigParser + +Config = ConfigParser.ConfigParser() +Config.read('wunderground/config/config.ini') + +user_apiid = Config.get('weather_settings', 'user_apiid') +user_city = Config.get('weather_settings', 'user_city') +user_state = Config.get('weather_settings', 'user_state') + + +def getWeatherCondition(): + try: + url = "http://api.wunderground.com/api/" + url += "%s/conditions/q/%s/" % (user_apiid, user_state) + url += "%s.json" % user_city + req = urllib2.Request(url) + response = urllib2.urlopen(req) + jsondata = response.read() + return jsondata + except Exception as e: + print("Could not get weather data") + return e + + +def pull_weather_json(): + weather = getWeatherCondition() + w = json.loads(weather) + + # Grab Weather Data + currenttemp = float(w['current_observation']['temp_f']) + atmospressure = float(w['current_observation']['pressure_in']) + windspeed = float(w['current_observation']['wind_mph']) + humidity = w['current_observation']['relative_humidity'] + humidity = humidity[:-1] + humidity = float(humidity) + feels_like = float(w['current_observation']['feelslike_f']) + dewpoint = float(w['current_observation']['dewpoint_f']) + + return currenttemp + + +def get_current_temperature(): + return pull_weather_json() + +