mirror of
https://github.com/CCOSTAN/Home-AssistantConfig.git
synced 2025-02-22 17:06:15 +00:00
265 lines
8.7 KiB
Python
265 lines
8.7 KiB
Python
#! /usr/bin/python
|
|
# -*- coding:utf-8 -*-
|
|
|
|
'''
|
|
nest.py -- a python interface to the Nest Thermostats
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
|
|
from . import nest
|
|
from . import utils
|
|
from . import helpers
|
|
|
|
|
|
def parse_args():
|
|
prog = os.path.basename(sys.argv[0])
|
|
config_file = os.path.sep.join(('~', '.config', prog, 'config'))
|
|
|
|
conf_parser = argparse.ArgumentParser(prog=prog, add_help=False)
|
|
conf_parser.add_argument('--conf', default=config_file,
|
|
help='config file (default %s)' % config_file,
|
|
metavar='FILE')
|
|
|
|
args, remaining_argv = conf_parser.parse_known_args()
|
|
|
|
defaults = helpers.get_config(config_path=args.conf)
|
|
|
|
description = 'Command line interface to Nest™ Thermostats'
|
|
parser = argparse.ArgumentParser(description=description,
|
|
parents=[conf_parser])
|
|
|
|
parser.set_defaults(**defaults)
|
|
|
|
parser.add_argument('--token-cache', dest='token_cache',
|
|
help='auth access token cache file',
|
|
metavar='TOKEN_CACHE_FILE')
|
|
|
|
parser.add_argument('-t', '--token', dest='token',
|
|
help='auth access token', metavar='TOKEN')
|
|
|
|
parser.add_argument('-u', '--user', dest='user',
|
|
help='username for nest.com', metavar='USER')
|
|
|
|
parser.add_argument('-p', '--password', dest='password',
|
|
help='password for nest.com', metavar='PASSWORD')
|
|
|
|
parser.add_argument('-c', '--celsius', dest='celsius', action='store_true',
|
|
help='use celsius instead of farenheit')
|
|
|
|
parser.add_argument('-s', '--serial', dest='serial',
|
|
help='optional, specify serial number of nest '
|
|
'thermostat to talk to')
|
|
|
|
parser.add_argument('-S', '--structure', dest='structure',
|
|
help='optional, specify structure name to'
|
|
'scope device actions')
|
|
|
|
parser.add_argument('-i', '--index', dest='index', default=0, type=int,
|
|
help='optional, specify index number of nest to '
|
|
'talk to')
|
|
|
|
subparsers = parser.add_subparsers(dest='command',
|
|
help='command help')
|
|
temp = subparsers.add_parser('temp', help='show/set temperature')
|
|
temp.add_argument('temperature', nargs='*', type=float,
|
|
help='target tempterature to set device to')
|
|
|
|
fan = subparsers.add_parser('fan', help='set fan "on" or "auto"')
|
|
fan_group = fan.add_mutually_exclusive_group()
|
|
fan_group.add_argument('--auto', action='store_true', default=False,
|
|
help='set fan to auto')
|
|
fan_group.add_argument('--on', action='store_true', default=False,
|
|
help='set fan to on')
|
|
|
|
mode = subparsers.add_parser('mode', help='show/set current mode')
|
|
mode_group = mode.add_mutually_exclusive_group()
|
|
mode_group.add_argument('--cool', action='store_true', default=False,
|
|
help='set mode to cool')
|
|
mode_group.add_argument('--heat', action='store_true', default=False,
|
|
help='set mode to heat')
|
|
mode_group.add_argument('--range', action='store_true', default=False,
|
|
help='set mode to range')
|
|
mode_group.add_argument('--off', action='store_true', default=False,
|
|
help='set mode to off')
|
|
|
|
away = subparsers.add_parser('away', help='show/set current away status')
|
|
away_group = away.add_mutually_exclusive_group()
|
|
away_group.add_argument('--away', action='store_true', default=False,
|
|
help='set away status to "away"')
|
|
away_group.add_argument('--home', action='store_true', default=False,
|
|
help='set away status to "home"')
|
|
|
|
subparsers.add_parser('target', help='show current temp target')
|
|
subparsers.add_parser('humid', help='show current humidity')
|
|
|
|
target_hum = subparsers.add_parser('target_hum',
|
|
help='show/set target humidty')
|
|
target_hum.add_argument('humidity', nargs='*',
|
|
help='specify target humidity value or auto '
|
|
'to auto-select a humidity based on outside '
|
|
'temp')
|
|
|
|
subparsers.add_parser('show', help='show everything')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
def _identity(x):
|
|
return x
|
|
|
|
if args.celsius:
|
|
display_temp = _identity
|
|
convert_temp = _identity
|
|
|
|
else:
|
|
display_temp = utils.c_to_f
|
|
convert_temp = utils.f_to_c
|
|
|
|
cmd = args.command
|
|
|
|
token_cache = None
|
|
if args.token_cache:
|
|
token_cache = os.path.expanduser(args.token_cache)
|
|
|
|
# NOTE(jkoelker) Token caching is currently broken
|
|
token_cache = None
|
|
|
|
with nest.Nest(args.user, args.password, access_token=args.token,
|
|
access_token_cache_file=token_cache) as napi:
|
|
if cmd == 'away':
|
|
structure = None
|
|
|
|
if args.structure:
|
|
struct = [s for s in napi.structures
|
|
if s.name == args.structure]
|
|
if struct:
|
|
structure = struct[0]
|
|
|
|
else:
|
|
if args.serial:
|
|
serial = args.serial
|
|
else:
|
|
serial = napi.devices[args.index]._serial
|
|
|
|
struct = [s for s in napi.structures for d in s.devices
|
|
if d._serial == serial]
|
|
if struct:
|
|
structure = struct[0]
|
|
|
|
if not structure:
|
|
structure = napi.structures[0]
|
|
|
|
if args.away:
|
|
structure.away = True
|
|
|
|
elif args.home:
|
|
structure.away = False
|
|
|
|
print(structure.away)
|
|
return
|
|
|
|
if args.serial:
|
|
device = nest.Device(args.serial, napi)
|
|
|
|
elif args.structure:
|
|
struct = [s for s in napi.structures if s.name == args.structure]
|
|
if struct:
|
|
device = struct[0].devices[args.index]
|
|
|
|
else:
|
|
device = napi.structures[0].devices[args.index]
|
|
|
|
else:
|
|
device = napi.devices[args.index]
|
|
|
|
if cmd == 'temp':
|
|
if args.temperature:
|
|
if len(args.temperature) > 1:
|
|
if device.mode != 'range':
|
|
device.mode = 'range'
|
|
|
|
lower = convert_temp(args.temperature[0])
|
|
upper = convert_temp(args.temperature[1])
|
|
device.temperature = (lower, upper)
|
|
|
|
else:
|
|
temp = convert_temp(args.temperature[0])
|
|
device.temperature = temp
|
|
|
|
print('%0.1f' % display_temp(device.temperature))
|
|
|
|
elif cmd == 'fan':
|
|
if args.auto:
|
|
device.fan = False
|
|
|
|
elif args.on:
|
|
device.fan = True
|
|
|
|
print(device.fan)
|
|
|
|
elif cmd == 'mode':
|
|
if args.cool:
|
|
device.mode = 'cool'
|
|
|
|
elif args.heat:
|
|
device.mode = 'heat'
|
|
|
|
elif args.range:
|
|
device.mode = 'range'
|
|
|
|
elif args.off:
|
|
device.mode = 'off'
|
|
|
|
print(device.mode)
|
|
|
|
elif cmd == 'humid':
|
|
print(device.humidity)
|
|
|
|
elif cmd == 'target_hum':
|
|
if args.humidity:
|
|
device.target_humidity = args.humidity[0]
|
|
|
|
print(device.target_humidity)
|
|
|
|
elif cmd == 'target':
|
|
target = device.target
|
|
|
|
if isinstance(target, tuple):
|
|
print('Lower: %0.1f' % display_temp(target[0]))
|
|
print('Upper: %0.1f' % display_temp(target[1]))
|
|
|
|
else:
|
|
print('%0.1f' % display_temp(target))
|
|
|
|
elif cmd == 'show':
|
|
data = device._shared.copy()
|
|
data.update(device._device)
|
|
|
|
for k in sorted(data.keys()):
|
|
intag = any(intag in k for intag in ('temp', 'away',
|
|
'threshold'))
|
|
nottag = any(notag in k for notag in ('type', 'pin_hash',
|
|
'scale', 'enabled'))
|
|
if intag and not nottag:
|
|
try:
|
|
temp_data = '%0.1f' % display_temp(data[k])
|
|
print(k + '.'*(35-len(k)) + ':', temp_data)
|
|
|
|
except Exception:
|
|
print(k + '.'*(35-len(k)) + ':', data[k])
|
|
|
|
else:
|
|
print(k + '.'*(35-len(k)) + ':', data[k])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|