#!/usr/bin/python

import pygatt
import time
import logging
import sys
import getopt
import ctypes

from pygatt.backends import BLEBackend, Characteristic, BLEAddressType

command = None
address = 'E3:61:5F:C0:FF:EE'
sendbytes = None
debuglogging = False
sleeponexit = True
sequences = []

commandmap = dict([
	("laugh", [0x0A,0x18,0x00,0x1F,0x00,0x32,0x00,0x00,0x00,0x00,0x00]),
	("yes", [0x0A,0x17,0x05,0x41,0x00,0x0F]),
	("no", [0x0A,0x17,0x05,0x3F,0x00,0x10]),
	("alarm", [0x0A,0x17,0x05,0x17,0x00,0x07]),
	("angry", [0x0A,0x17,0x05,0x18,0x00,0x08]),
	("annoyed", [0x0A,0x17,0x05,0x19,0x00,0x09]),
	("ionblast", [0x0A,0x17,0x05,0x1A,0x00,0x0E]),
	("sad", [0x0A,0x17,0x05,0x1C,0x00,0x11]),
	("scared", [0x0A,0x17,0x05,0x1D,0x00,0x13]),
	("chatty", [0x0A,0x17,0x05,0x17,0x00,0x0A]),
	("confident", [0x0A,0x17,0x05,0x18,0x00,0x12]),
	("excited", [0x0A,0x17,0x05,0x19,0x00,0x0C]),
	("happy", [0x0A,0x17,0x05,0x1A,0x00,0x0D]),
	("laugh", [0x0A,0x17,0x05,0x1B,0x00,0x0F]),
	("surprise", [0x0A,0x17,0x05,0x1C,0x00,0x18]),
	("tripod", [0x0A,0x17,0x0D,0x1D,0x01]),
	("bipod", [0x0A,0x17,0x0D,0x1C,0x02])
	])

# The CRC is 256 modulus sum of all the bytes, bitwise inverted
def GenCrc(bytes):
	ret = 0;
	for b in bytes:
		ret += b
		ret = ret % 256
	
	return ~ret % 256

def BuildPacket(bytes):
	# 0x8D marks the start of a packet
	ret = [0x8D]
	for b in bytes:
		ret.append(b)

	# CRC is always the 2nd to last byte
	ret.append(GenCrc(bytes))

	# 0xD8 marks the end of a packet
	ret.append(0xD8)
	return ret

try:
	opts, args = getopt.getopt(sys.argv[1:], "a:c:dn", ["address=", "command=", "debug", "nosleep"])
except getopt.GetoptError as err:
	print(err)
	sys.exit(1)

for o, a in opts:
	if o in ("-a", "--address"):
		address = a
	elif o in ("-c", "--command"):
		command = a
		if command == "list":
			for cmdopt in commandmap:
				print cmdopt
			sys.exit(0)
		sequences.append(commandmap[a])
	elif o in ("-d", "--debug"):
		debuglogging = True
	elif o in ("-n", "--nosleep"):
		sleeponexit = False
	else:
		assert False, "unhandled option"


if command == None:
	print "A command must be specified.  Use -c list to get a list of commands"
	sys.exit(1)

logging.basicConfig()
if debuglogging == True:
	logging.getLogger('pygatt').setLevel(logging.DEBUG)

adapter = pygatt.GATTToolBackend()

adapter.start()
device = adapter.connect(address=address, address_type=BLEAddressType.random)

# 'usetheforce...band' tells the droid we're a controller, I guess.  Prevents disconnection.
device.char_write_handle(0x15, [0x75,0x73,0x65,0x74,0x68,0x65,0x66,0x6F,0x72,0x63,0x65,0x2E,0x2E,0x2E,0x62,0x61,0x6E,0x64], True)

# wake from sleep?  Droid is responsive and front led flashes blue/red
device.char_write_handle(0x1c, [0x8D,0x0A,0x13,0x0D,0x00,0xD5,0xD8], True)

# Turn on holoprojector led, 0xff (max) intensity
device.char_write_handle(0x1c, [0x8D,0x0A,0x1A,0x0E,0x1C,0x00,0x80,0xFF,0x32,0xD8], True)

for seq in sequences:
	#device.char_write_handle(0x1c, commandmap[command], True)
	device.char_write_handle(0x1c, BuildPacket(seq), True)
	time.sleep(2)

# rotate top to -90 degrees
#device.char_write_handle(0x1c, [0x8D,0x0A,0x17,0x0F,0x1C,0x42,0xB4,0x00,0x00,0xBD,0xD8], True)
#time.sleep(5)

# rotate top to 0 degrees
#device.char_write_handle(0x1c, [0x8D,0x0A,0x17,0x0F,0x1E,0x00,0x00,0x00,0x00,0xB1,0xD8], True)
#time.sleep(5)

if sleeponexit:
	# put the droid to sleep
	device.char_write_handle(0x1c, [0x8D,0x0A,0x13,0x01,0x17,0xCA,0xD8], True)
adapter.stop()
