#!/usr/bin/env python3
# Copyright (c) 2016 <NAME>
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
"""
Controller for the Embrava Blynclight (BLYNCUSB30-152) USB LED indicator.
"""
from argparse import ArgumentParser
from math import pow, sin, cos, fabs, pi
from time import sleep
import sys
import usb
import usb.core
import usb.util
# import usb.backend.openusb as openusb

class BlynclightNotFound(Exception):
	pass

class Blynclight(object):
	BLYNCLIGHT_VENDOR  = 0x0e53
	BLYNCLIGHT_PRODUCT = 0x2516

	def __init__(self):
		"""Constructor"""
		self.dev = usb.core.find(idVendor=self.BLYNCLIGHT_VENDOR,
		                         idProduct=self.BLYNCLIGHT_PRODUCT)
		if self.dev is None:
			raise BlynclightNotFound()

		for cfg in self.dev:
			for intf in cfg:
				if self.dev.is_kernel_driver_active(intf.bInterfaceNumber):
					self.dev.detach_kernel_driver(intf.bInterfaceNumber)

		self.dev.set_configuration()
		# print(self.dev)

	def set_rbg(self, r, b, g):
		# Clamp RBG to [0, 255]
		r = int(max(0, min(r, 255)))
		b = int(max(0, min(b, 255)))
		g = int(max(0, min(g, 255)))
		d = (r, b, g, 0x00, 0x00, 0x00, 0xff, 0xff)
		self.dev.ctrl_transfer(0x21, 0x9, 0x0200, 0, d, 0)
		print("ending")


def cycleServer(color, iterations, speed=0.5):
	bl = Blynclight()
	t = 0.0
	refresh = 0.017
	while True:
		t += speed*refresh
		r = int(256 * pow(sin(t        ), 8))
		b = int(256 * pow(sin(t+0.66*pi), 8))
		g = int(256 * pow(sin(t+0.33*pi), 8))
		# if mode == "verbose": print("%d,%d,%d" % (r,b,g))
		bl.set_rbg(r, b, g)
		sleep(refresh)


def color(args):
	"""Set a specific color"""
	bl = Blynclight()
	bl.set_rbg(int(args.red), int(args.blue), int(args.green))


def pulseServer(color, speed=0.5, iterations=3):
	"""Pulse a specific color"""
	bl = Blynclight()
	t = 0.0
	refresh = 0.017
	# i = 0
	while iterations > 0:
		if color == "red": 
			print('RED')
			r, g, b = 255, 0 , 0
		if color == "green": 
			print('GREEN')
			r, g, b = 0, 255, 0
		if color == "blue":
			print('BLUE') 
			r, g, b = 0, 0, 255
		if color == "orange":
			print('ORANGE')
			r, g, b = 255, 30, 0
		bl.set_rbg(r, b, g)
		sleep(speed)
		bl.set_rbg(0, 0, 0)
		sleep(speed)
		iterations -= 1
	return

def flashServer(color, speed=0.5, iterations=0):
	bl = Blynclight()
	if color == "red": 
		r, g, b = 255, 0 , 0
	if color == "green": 
		r, g, b = 0, 255, 0
	if color == "blue": 
		r, g, b = 0, 0, 255
	if color == "orange":
		print("ORANGE")
		r, g, b = 255, 20, 0
	bl.set_rbg(r, g, b,)
	bl.set_rbg(0, 0, 0)
	return


def main():
	#bl = Blynclight()
	#bl.set_rbg(60, 60, 60)
	parser = ArgumentParser()
	parser.add_argument('--verbose', action='store_true')
	subparsers = parser.add_subparsers(title='command', dest='command')
	subparsers.required=True

	cmd_cycle = subparsers.add_parser('cycle', help=cycle.__doc__)
	cmd_cycle.add_argument('--speed', type=float)
	cmd_cycle.set_defaults(func=cycle, speed=0.5)

	cmd_color = subparsers.add_parser('color', help=color.__doc__)
	cmd_color.add_argument('red', type=int, help='Red intensity [0,255]')
	cmd_color.add_argument('blue', type=int, help='Blue intensity [0,255]')
	cmd_color.add_argument('green', type=int, help='Green intensity [0,255]')
	cmd_color.set_defaults(func=color)

	cmd_pulse = subparsers.add_parser('pulse', help=pulse.__doc__)
	cmd_pulse.add_argument('--speed', type=float)
	cmd_pulse.add_argument('--iterations', type=int, help='Number of pulses')
	cmd_pulse.add_argument('red', type=int, help='Red intensity [0,255]')
	cmd_pulse.add_argument('blue', type=int, help='Blue intensity [0,255]')
	cmd_pulse.add_argument('green', type=int, help='Green intensity [0,255]')
	cmd_pulse.set_defaults(func=pulse, speed=4, iterations=3)

	args = parser.parse_args()

	try:
		args.func(args)
	except BlynclightNotFound as e:
		sys.stderr.write('Error: Could not find Blynclight. Is it plugged in?\n')
		sys.exit(1)

if __name__ == '__main__':
	main()

#!/usr/bin/env python3
# Copyright (c) 2016 <NAME>
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
"""
Controller for the Embrava Blynclight (BLYNCUSB30-152) USB LED indicator.
"""
from argparse import ArgumentParser
from math import pow, sin, cos, fabs, pi
from time import sleep
import sys
import usb
import usb.core
import usb.util
# import usb.backend.openusb as openusb

class BlynclightNotFound(Exception):
	pass

class Blynclight(object):
	BLYNCLIGHT_VENDOR  = 0x0e53
	BLYNCLIGHT_PRODUCT = 0x2516

	def __init__(self):
		"""Constructor"""
		self.dev = usb.core.find(idVendor=self.BLYNCLIGHT_VENDOR,
		                         idProduct=self.BLYNCLIGHT_PRODUCT)
		if self.dev is None:
			raise BlynclightNotFound()

		for cfg in self.dev:
			for intf in cfg:
				if self.dev.is_kernel_driver_active(intf.bInterfaceNumber):
					self.dev.detach_kernel_driver(intf.bInterfaceNumber)

		self.dev.set_configuration()
		# print(self.dev)

	def set_rbg(self, r, b, g):
		# Clamp RBG to [0, 255]
		r = int(max(0, min(r, 255)))
		b = int(max(0, min(b, 255)))
		g = int(max(0, min(g, 255)))
		d = (r, b, g, 0x00, 0x00, 0x00, 0xff, 0xff)
		self.dev.ctrl_transfer(0x21, 0x9, 0x0200, 0, d, 0)
		print("ending")


def cycleServer(color, iterations, speed=0.5):
	bl = Blynclight()
	t = 0.0
	refresh = 0.017
	while True:
		t += speed*refresh
		r = int(256 * pow(sin(t        ), 8))
		b = int(256 * pow(sin(t+0.66*pi), 8))
		g = int(256 * pow(sin(t+0.33*pi), 8))
		# if mode == "verbose": print("%d,%d,%d" % (r,b,g))
		bl.set_rbg(r, b, g)
		sleep(refresh)


def color(args):
	"""Set a specific color"""
	bl = Blynclight()
	bl.set_rbg(int(args.red), int(args.blue), int(args.green))


def pulseServer(color, speed=0.5, iterations=3):
	"""Pulse a specific color"""
	bl = Blynclight()
	t = 0.0
	refresh = 0.017
	# i = 0
	while iterations > 0:
		if color == "red": 
			print('RED')
			r, g, b = 255, 0 , 0
		if color == "green": 
			print('GREEN')
			r, g, b = 0, 255, 0
		if color == "blue":
			print('BLUE') 
			r, g, b = 0, 0, 255
		if color == "orange":
			print('ORANGE')
			r, g, b = 255, 30, 0
		bl.set_rbg(r, b, g)
		sleep(speed)
		bl.set_rbg(0, 0, 0)
		sleep(speed)
		iterations -= 1
	return

def flashServer(color, speed=0.5, iterations=0):
	bl = Blynclight()
	if color == "red": 
		r, g, b = 255, 0 , 0
	if color == "green": 
		r, g, b = 0, 255, 0
	if color == "blue": 
		r, g, b = 0, 0, 255
	if color == "orange":
		print("ORANGE")
		r, g, b = 255, 20, 0
	bl.set_rbg(r, g, b,)
	bl.set_rbg(0, 0, 0)
	return


def main():
	#bl = Blynclight()
	#bl.set_rbg(60, 60, 60)
	parser = ArgumentParser()
	parser.add_argument('--verbose', action='store_true')
	subparsers = parser.add_subparsers(title='command', dest='command')
	subparsers.required=True

	cmd_cycle = subparsers.add_parser('cycle', help=cycle.__doc__)
	cmd_cycle.add_argument('--speed', type=float)
	cmd_cycle.set_defaults(func=cycle, speed=0.5)

	cmd_color = subparsers.add_parser('color', help=color.__doc__)
	cmd_color.add_argument('red', type=int, help='Red intensity [0,255]')
	cmd_color.add_argument('blue', type=int, help='Blue intensity [0,255]')
	cmd_color.add_argument('green', type=int, help='Green intensity [0,255]')
	cmd_color.set_defaults(func=color)

	cmd_pulse = subparsers.add_parser('pulse', help=pulse.__doc__)
	cmd_pulse.add_argument('--speed', type=float)
	cmd_pulse.add_argument('--iterations', type=int, help='Number of pulses')
	cmd_pulse.add_argument('red', type=int, help='Red intensity [0,255]')
	cmd_pulse.add_argument('blue', type=int, help='Blue intensity [0,255]')
	cmd_pulse.add_argument('green', type=int, help='Green intensity [0,255]')
	cmd_pulse.set_defaults(func=pulse, speed=4, iterations=3)

	args = parser.parse_args()

	try:
		args.func(args)
	except BlynclightNotFound as e:
		sys.stderr.write('Error: Could not find Blynclight. Is it plugged in?\n')
		sys.exit(1)

if __name__ == '__main__':
	main()

#!/usr/bin/env python3 # Copyright (c) 2016 <NAME> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. Controller for the Embrava Blynclight (BLYNCUSB30-152) USB LED indicator. # import usb.backend.openusb as openusb Constructor # print(self.dev) # Clamp RBG to [0, 255] # if mode == "verbose": print("%d,%d,%d" % (r,b,g)) Set a specific color Pulse a specific color # i = 0 #bl = Blynclight() #bl.set_rbg(60, 60, 60)