#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, getopt, httplib, urllib, json, os
import oauth.oauth as oauth
import datetime
from configobj import ConfigObj
import logging 

global logger
logger = logging.getLogger(os.path.basename(__file__))
import davan.util.application_logger as log_manager
#insert your own public_key and private_key
import davan.config.config_creator as config_creator
configuration = config_creator.create()
PUBLIC_KEY = configuration["TELLDUS_PUBLIC_KEY"]
PRIVATE_KEY = configuration["TELLDUS_PRIVATE_KEY"]

TELLSTICK_TURNON = 1
TELLSTICK_TURNOFF = 2
TELLSTICK_BELL = 4
TELLSTICK_DIM = 16
TELLSTICK_UP = 128
TELLSTICK_DOWN = 256

SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_UP | TELLSTICK_DOWN;

def printUsage():
	print("Usage: %s [ options ]" % sys.argv[0])
	print("")
	print("Options:")
	print("         -[lnfdbvh] [ --list ] [ --help ]")
	print("                      [ --on device ] [ --off device ] [ --bell device ]")
	print("                      [ --dimlevel level --dim device ]")
	print("                      [ --up device --down device ]")
	print("")
	print("       --list (-l short option)")
	print("             List currently configured devices.")
	print("")
	print("       --help (-h short option)")
	print("             Shows this screen.")
	print("")
	print("       --on device (-n short option)")
	print("             Turns on device. 'device' must be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("")
	print("       --off device (-f short option)")
	print("             Turns off device. 'device' must be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("")
	print("       --dim device (-d short option)")
	print("             Dims device. 'device' must be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("             Note: The dimlevel parameter must be set before using this option.")
	print("")
	print("       --dimlevel level (-v short option)")
	print("             Set dim level. 'level' should an integer, 0-255.")
	print("             Note: This parameter must be set before using dim.")
	print("")
	print("       --bell device (-b short option)")
	print("             Sends bell command to devices supporting this. 'device' must")
	print("             be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("")
	print("       --up device")
	print("             Sends up command to devices supporting this. 'device' must")
	print("             be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("")
	print("       --down device")
	print("             Sends down command to devices supporting this. 'device' must")
	print("             be an integer of the device-id")
	print("             Device-id and name is outputed with the --list option")
	print("")
	print("       --list-sensors (-s short option)")
	print("             Lists currently configured sensors")
	print("")
	print("       --sensor-data sensor (-d short option)")
	print("             Get sensor data with sensor id number")
	print("")
	print("Report bugs to <info.tech@telldus.se>")

def listSensors():
	response = doRequest('sensors/list', {'includeIgnored': 1});
	logger.debug("Number of sensors: %i" % len(response['sensor']));
	for sensor in response['sensor']:
		lastupdate = datetime.datetime.fromtimestamp(int(sensor['lastUpdated']));
		logger.debug( "%s\t%s\t%s" % (sensor['id'], sensor['name'], lastupdate))


def listSensorsAndValues():
	response = doRequest('sensors/list', {'includeValues': 1});
	return response

def listDevicesAndValues():
	response = doRequest('devices/list', {'supportedMethods': SUPPORTED_METHODS})
	return response

def getSensorData(sensorId):
	response = doRequest('sensor/info', {'id': sensorId });
	lastupdate = datetime.datetime.fromtimestamp(int(response['lastUpdated']));
	sensor_name = response['name'];
	for data in response['data']:
		logger.debug( "%s\t%s\t%s\t%s" % (sensor_name, data['name'], data['value'], lastupdate)	)

def listDevices():
	response = doRequest('devices/list', {'supportedMethods': SUPPORTED_METHODS})
	logger.debug("Number of devices: %i" % len(response['device']));
	for device in response['device']:
		if (device['state'] == TELLSTICK_TURNON):
			state = 'ON'
		elif (device['state'] == TELLSTICK_TURNOFF):
			state = 'OFF'
		elif (device['state'] == TELLSTICK_DIM):
			state = "DIMMED"
		elif (device['state'] == TELLSTICK_UP):
			state = "UP"
		elif (device['state'] == TELLSTICK_DOWN):
			state = "DOWN"
		else:
			state = 'Unknown state'

		logger.debug("%s\t%s\t%s" % (device['id'], device['name'], state));

def doMethod(deviceId, methodId, methodValue = 0):
	response = doRequest('device/info', {'id': deviceId})

	if (methodId == TELLSTICK_TURNON):
		method = 'on'
	elif (methodId == TELLSTICK_TURNOFF):
		method = 'off'
	elif (methodId == TELLSTICK_BELL):
		method = 'bell'
	elif (methodId == TELLSTICK_UP):
		method = 'up'
	elif (methodId == TELLSTICK_DOWN):
		method = 'down'

	if ('error' in response):
		name = ''
		retString = response['error']
	else:
		name = response['name']
		response = doRequest('device/command', {'id': deviceId, 'method': methodId, 'value': methodValue})
		if ('error' in response):
			retString = response['error']
		else:
			retString = response['status']

	if (methodId in (TELLSTICK_TURNON, TELLSTICK_TURNOFF)):
		logger.debug("Turning %s device %s, %s - %s" % ( method, deviceId, name, retString));
	elif (methodId in (TELLSTICK_BELL, TELLSTICK_UP, TELLSTICK_DOWN)):
		logger.debug("Sending %s to: %s %s - %s" % (method, deviceId, name, retString))
	elif (methodId == TELLSTICK_DIM):
		logger.debug("Dimming device: %s %s to %s - %s" % (deviceId, name, methodValue, retString))


def doRequest(method, params):
	global config
	config = ConfigObj(os.environ['HOME'] + '/.config/Telldus/tdtool.conf')

	consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY)
	token = oauth.OAuthToken(config['token'], config['tokenSecret'])

	oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url="http://api.telldus.com/json/" + method, parameters=params)
	oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, token)
	headers = oauth_request.to_header()
	headers['Content-Type'] = 'application/x-www-form-urlencoded'

	conn = httplib.HTTPConnection("api.telldus.com:80")
	conn.request('GET', "/json/" + method + "?" + urllib.urlencode(params, True).replace('+', '%20'), headers=headers)

	response = conn.getresponse()
	try:	
		return json.load(response)
	except:
		logger.debug( 'Failed to decode response :%s'%str(response))
		return ""

def requestToken():
	global config
	consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY)
	request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url='http://api.telldus.com/oauth/requestToken')
	request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None)
	conn = httplib.HTTPConnection('api.telldus.com:80')
	conn.request(request.http_method, '/oauth/requestToken', headers=request.to_header())

	resp = conn.getresponse().read()
	token = oauth.OAuthToken.from_string(resp)
	logger.debug( 'Open the following url in your webbrowser:\nhttp://api.telldus.com/oauth/authorize?oauth_token=%s\n' % token.key)
	logger.debug( 'After logging in and accepting to use this application run:\n%s --authenticate' % (sys.argv[0]))
	config['requestToken'] = str(token.key)
	config['requestTokenSecret'] = str(token.secret)
	saveConfig()

def getAccessToken():
	global config
	consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY)
	token = oauth.OAuthToken(config['requestToken'], config['requestTokenSecret'])
	request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url='http://api.telldus.com/oauth/accessToken')
	request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, token)
	conn = httplib.HTTPConnection('api.telldus.com:80')
	conn.request(request.http_method, request.to_url(), headers=request.to_header())

	resp = conn.getresponse()
	if resp.status != 200:
		logger.debug( 'Error retreiving access token, the server replied:\n%s' % resp.read())
		return
	token = oauth.OAuthToken.from_string(resp.read())
	config['requestToken'] = None
	config['requestTokenSecret'] = None
	config['token'] = str(token.key)
	config['tokenSecret'] = str(token.secret)
	logger.debug( 'Authentication successful, you can now use tdtool')
	saveConfig()

def authenticate():
	try:
		opts, args = getopt.getopt(sys.argv[1:], '', ['authenticate'])
		for opt, arg in opts:
			if opt in ('--authenticate'):
				getAccessToken()
				return
	except getopt.GetoptError:
		pass
	requestToken()

def saveConfig():
	global config
	try:
		os.makedirs(os.environ['HOME'] + '/.config/Telldus')
	except:
		pass
	config.write()

def main(argv):
	global config
	if ('token' not in config or config['token'] == ''):
		authenticate()
		return
	try:
		opts, args = getopt.getopt(argv, "lsd:n:f:d:b:v:h", ["list", "list-sensors", "sensor-data=", "on=", "off=", "dim=", "bell=", "dimlevel=", "up=", "down=", "help"])
	except getopt.GetoptError:
		printUsage()
		sys.exit(2)

	dimlevel = -1

	for opt, arg in opts:
		if opt in ("-h", "--help"):
			printUsage()

		elif opt in ("-l", "--list"):
			listDevices()

		elif opt in ("-s", "--list-sensors"):
			listSensors()

		elif opt in ("-x", "--list-sensorsvalue"):
			listSensorsAndValues()

		elif opt in ("-d", "--sensor-data"):
			getSensorData(arg)

		elif opt in ("-n", "--on"):
			doMethod(arg, TELLSTICK_TURNON)

		elif opt in ("-f", "--off"):
			doMethod(arg, TELLSTICK_TURNOFF)

		elif opt in ("-b", "--bell"):
			doMethod(arg, TELLSTICK_BELL)

		elif opt in ("-d", "--dim"):
			if (dimlevel < 0):
				logger.debug("Dimlevel must be set with --dimlevel before --dim")
			else:
				doMethod(arg, TELLSTICK_DIM, dimlevel)

		elif opt in ("-v", "--dimlevel"):
			dimlevel = arg

		elif opt in ("--up"):
			doMethod(arg, TELLSTICK_UP)

		elif opt in ("--down"):
			doMethod(arg, TELLSTICK_DOWN)

if __name__ == "__main__":
	config = ConfigObj(os.environ['HOME'] + '/.config/Telldus/tdtool.conf')
	configuration = config_creator.create()
	log_manager.start_logging(configuration["LOGFILE_PATH"],loglevel=4)
	main(sys.argv[1:])

[((15, 16, 15, 39), 'davan.config.config_creator.create', 'config_creator.create', ({}, {}), '()', True, 'import davan.config.config_creator as config_creator\n'), ((11, 27, 11, 53), 'os.path.basename', 'os.path.basename', ({(11, 44, 11, 52): '__file__'}, {}), '(__file__)', False, 'import sys, getopt, httplib, urllib, json, os\n'), ((160, 10, 160, 72), 'configobj.ConfigObj', 'ConfigObj', ({(160, 20, 160, 71): "os.environ['HOME'] + '/.config/Telldus/tdtool.conf'"}, {}), "(os.environ['HOME'] + '/.config/Telldus/tdtool.conf')", False, 'from configobj import ConfigObj\n'), ((162, 12, 162, 56), 'oauth.oauth.OAuthConsumer', 'oauth.OAuthConsumer', ({(162, 32, 162, 42): 'PUBLIC_KEY', (162, 44, 162, 55): 'PRIVATE_KEY'}, {}), '(PUBLIC_KEY, PRIVATE_KEY)', True, 'import oauth.oauth as oauth\n'), ((163, 9, 163, 65), 'oauth.oauth.OAuthToken', 'oauth.OAuthToken', ({(163, 26, 163, 41): "config['token']", (163, 43, 163, 64): "config['tokenSecret']"}, {}), "(config['token'], config['tokenSecret'])", True, 'import oauth.oauth as oauth\n'), ((165, 17, 165, 170), 'oauth.oauth.OAuthRequest.from_consumer_and_token', 'oauth.OAuthRequest.from_consumer_and_token', (), '', True, 'import oauth.oauth as oauth\n'), ((170, 8, 170, 52), 'httplib.HTTPConnection', 'httplib.HTTPConnection', ({(170, 31, 170, 51): '"""api.telldus.com:80"""'}, {}), "('api.telldus.com:80')", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((182, 12, 182, 56), 'oauth.oauth.OAuthConsumer', 'oauth.OAuthConsumer', ({(182, 32, 182, 42): 'PUBLIC_KEY', (182, 44, 182, 55): 'PRIVATE_KEY'}, {}), '(PUBLIC_KEY, PRIVATE_KEY)', True, 'import oauth.oauth as oauth\n'), ((183, 11, 183, 117), 'oauth.oauth.OAuthRequest.from_consumer_and_token', 'oauth.OAuthRequest.from_consumer_and_token', (), '', True, 'import oauth.oauth as oauth\n'), ((185, 8, 185, 52), 'httplib.HTTPConnection', 'httplib.HTTPConnection', ({(185, 31, 185, 51): '"""api.telldus.com:80"""'}, {}), "('api.telldus.com:80')", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((189, 9, 189, 43), 'oauth.oauth.OAuthToken.from_string', 'oauth.OAuthToken.from_string', ({(189, 38, 189, 42): 'resp'}, {}), '(resp)', True, 'import oauth.oauth as oauth\n'), ((198, 12, 198, 56), 'oauth.oauth.OAuthConsumer', 'oauth.OAuthConsumer', ({(198, 32, 198, 42): 'PUBLIC_KEY', (198, 44, 198, 55): 'PRIVATE_KEY'}, {}), '(PUBLIC_KEY, PRIVATE_KEY)', True, 'import oauth.oauth as oauth\n'), ((199, 9, 199, 79), 'oauth.oauth.OAuthToken', 'oauth.OAuthToken', ({(199, 26, 199, 48): "config['requestToken']", (199, 50, 199, 78): "config['requestTokenSecret']"}, {}), "(config['requestToken'], config['requestTokenSecret'])", True, 'import oauth.oauth as oauth\n'), ((200, 11, 200, 148), 'oauth.oauth.OAuthRequest.from_consumer_and_token', 'oauth.OAuthRequest.from_consumer_and_token', (), '', True, 'import oauth.oauth as oauth\n'), ((202, 8, 202, 52), 'httplib.HTTPConnection', 'httplib.HTTPConnection', ({(202, 31, 202, 51): '"""api.telldus.com:80"""'}, {}), "('api.telldus.com:80')", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((290, 10, 290, 72), 'configobj.ConfigObj', 'ConfigObj', ({(290, 20, 290, 71): "os.environ['HOME'] + '/.config/Telldus/tdtool.conf'"}, {}), "(os.environ['HOME'] + '/.config/Telldus/tdtool.conf')", False, 'from configobj import ConfigObj\n'), ((291, 17, 291, 40), 'davan.config.config_creator.create', 'config_creator.create', ({}, {}), '()', True, 'import davan.config.config_creator as config_creator\n'), ((292, 1, 292, 68), 'davan.util.application_logger.start_logging', 'log_manager.start_logging', (), '', True, 'import davan.util.application_logger as log_manager\n'), ((166, 28, 166, 66), 'oauth.oauth.OAuthSignatureMethod_HMAC_SHA1', 'oauth.OAuthSignatureMethod_HMAC_SHA1', ({}, {}), '()', True, 'import oauth.oauth as oauth\n'), ((175, 9, 175, 28), 'json.load', 'json.load', ({(175, 19, 175, 27): 'response'}, {}), '(response)', False, 'import sys, getopt, httplib, urllib, json, os\n'), ((184, 22, 184, 60), 'oauth.oauth.OAuthSignatureMethod_HMAC_SHA1', 'oauth.OAuthSignatureMethod_HMAC_SHA1', ({}, {}), '()', True, 'import oauth.oauth as oauth\n'), ((201, 22, 201, 60), 'oauth.oauth.OAuthSignatureMethod_HMAC_SHA1', 'oauth.OAuthSignatureMethod_HMAC_SHA1', ({}, {}), '()', True, 'import oauth.oauth as oauth\n'), ((219, 15, 219, 64), 'getopt.getopt', 'getopt.getopt', ({(219, 29, 219, 41): 'sys.argv[1:]', (219, 43, 219, 45): '""""""', (219, 47, 219, 63): "['authenticate']"}, {}), "(sys.argv[1:], '', ['authenticate'])", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((231, 2, 231, 54), 'os.makedirs', 'os.makedirs', ({(231, 14, 231, 53): "(os.environ['HOME'] + '/.config/Telldus')"}, {}), "(os.environ['HOME'] + '/.config/Telldus')", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((242, 15, 242, 164), 'getopt.getopt', 'getopt.getopt', ({(242, 29, 242, 33): 'argv', (242, 35, 242, 52): '"""lsd:n:f:d:b:v:h"""', (242, 54, 242, 163): "['list', 'list-sensors', 'sensor-data=', 'on=', 'off=', 'dim=', 'bell=',\n    'dimlevel=', 'up=', 'down=', 'help']"}, {}), "(argv, 'lsd:n:f:d:b:v:h', ['list', 'list-sensors',\n    'sensor-data=', 'on=', 'off=', 'dim=', 'bell=', 'dimlevel=', 'up=',\n    'down=', 'help'])", False, 'import sys, getopt, httplib, urllib, json, os\n'), ((245, 2, 245, 13), 'sys.exit', 'sys.exit', ({(245, 11, 245, 12): '(2)'}, {}), '(2)', False, 'import sys, getopt, httplib, urllib, json, os\n'), ((171, 47, 171, 77), 'urllib.urlencode', 'urllib.urlencode', ({(171, 64, 171, 70): 'params', (171, 72, 171, 76): '(True)'}, {}), '(params, True)', False, 'import sys, getopt, httplib, urllib, json, os\n')]