Skip to content
Snippets Groups Projects
Commit e0d7703d authored by jkerdreu's avatar jkerdreu
Browse files

New color API, used @spawn to cleanup the code.

git-svn-id: https://redmine.imt-atlantique.fr/svn/xaal/code/Python/branches/0.7@2518 b32b6428-25c9-4566-ad07-03861ab6144f
parent 14611aad
Branches
No related tags found
No related merge requests found
......@@ -13,15 +13,40 @@ logger = logging.getLogger(__name__)
import gevent
from gevent.util import wrap_errors
from decorator import decorator
def retry_(func,*args,**kwargs):
cnt = 0
while 1:
try:
logger.warning("Calling %s" % func)
func(*args,**kwargs)
break
except Exception as e:
if cnt == 0:
logger.warning(e)
cnt = cnt +1
if cnt == 2:
break
def retry(func,*args,**kwargs):
try:
logger.warning("Calling %s" % func)
func(*args,**kwargs)
except Exception as e:
logger.warning(e)
@decorator
def spawn(func,*args,**kwargs):
logger.warning("Calling %s" % func)
#gevent.spawn(retry(func,*args,**kwargs))
gevent.spawn(wrap_errors(Exception,func),*args,**kwargs)
#gevent.spawn(func,*args,**kwargs)
# we try twice within one second, if nothing works, just drop
TENACITY_RETRY=tenacity.stop_after_attempt(2) | tenacity.stop_after_delay(10)
def split_color(color):
data = color.split('#')[-1]
r = int(data[0:2],16)
g = int(data[2:4],16)
b = int(data[4:6],16)
return (r,g,b)
def properties_compare(orig,new):
r = {}
......@@ -39,12 +64,12 @@ class YeelightDev(object):
self.addr = addr
self.dev = None
self.setup()
self.get_properties()
self.set_xaal()
def debug_properties(self,properties):
if not hasattr(self,'last_properties'):
self.last_properties = properties
logger.warning(properties)
return
# for debugging only display changes
changes = properties_compare(self.last_properties,properties)
......@@ -63,79 +88,81 @@ class YeelightDev(object):
logger.warning('Please overide on_properties')
self.debug_properties(properties)
def spawn(self,func,*args,**kwargs):
gevent.spawn(wrap_errors(Exception,func),*args,**kwargs)
#gevent.spawn(func,*args,**kwargs)
def get_properties(self):
self.spawn(self._get_properties)
def on(self):
@spawn
def turn_on(self):
self.bulb.duration = 200
self.spawn(self._on)
def off(self):
self.bulb.duration = 5000
self.spawn(self._off)
def toggle(self):
self.spawn(self._toggle)
#===================================================
# Yeelight API
#===================================================
def _update_properties(self):
properties = self.bulb.get_properties()
self.on_properties(properties)
@tenacity.retry(stop=TENACITY_RETRY)
def _get_properties(self):
self._update_properties()
@tenacity.retry(stop=TENACITY_RETRY)
def _on(self):
self.bulb.turn_on()
self._update_properties()
@tenacity.retry(stop=TENACITY_RETRY)
def _off(self):
@spawn
def turn_off(self):
self.bulb.duration = 5000
self.bulb.turn_off()
self._update_properties()
@tenacity.retry(stop=TENACITY_RETRY)
def _toggle(self):
@spawn
def toggle(self):
self.bulb.toggle()
self._update_properties()
@spawn
def get_properties(self):
self._update_properties()
def _update_properties(self):
properties = self.bulb.get_properties()
self.on_properties(properties)
class RGBW(YeelightDev):
def setup(self):
dev = devices.lamp_rgbw(self.addr)
dev.methods['on'] = self.on
dev.methods['off'] = self.off
dev = devices.lamp_color(self.addr)
dev.methods['turn_on'] = self.turn_on
dev.methods['turn_off'] = self.turn_off
dev.methods['toggle'] = self.toggle
dev.methods['dim'] = self.dim
dev.methods['setRGB'] = self.set_color
dev.methods['setWhite'] = self.set_white
dev.methods['set_brightness'] = self.set_brightness
dev.methods['set_hsv'] = self.set_hsv
dev.methods['set_white_temperature'] = self.set_white_temperature
dev.methods['debug'] = self.debug
dev.info = 'RGBW / %s' % self.addr
dev.schema = 'https://redmine.telecom-bretagne.eu/svn/xaal/schemas/branches/schemas-0.7/lamp.dimmer'
dev.schema = 'https://redmine.telecom-bretagne.eu/svn/xaal/schemas/branches/schemas-0.7/lamp.color'
dev.attributes['hsv'] = [0,0,0]
self.dev = dev
self.flowing_timer = None
def debug(self):
import pdb;pdb.set_trace()
def dim(self,_target):
val = int(_target)
self.spawn(self._dim,val)
@spawn
def set_brightness(self,_brightness,_smooth=0):
val = int(_brightness)
self.bulb.turn_on()
self.bulb.set_brightness(val)
self._update_properties()
def set_color(self,_target):
r,g,b = split_color(_target)
self.spawn(self._set_color,r,g,b)
@spawn
def set_hsv(self,_hsv,_smooth=200):
# TBD
hsv = [float(k) for k in list(_hsv.split(','))]
h,s,v = hsv
v = int(v * 100)
s = int(s * 100)
h = int(h)
duration = int(_smooth)
if duration < 50:
duration = 50
self.bulb.turn_on()
self.bulb.duration = duration
self.bulb.set_hsv(h,s,v)
self._update_properties()
@spawn
def set_white_temperature(self,_white_temperature):
val = int(_white_temperature)
self.bulb.turn_on()
self.bulb.set_color_temp(val)
self._update_properties()
def set_white(self,_target):
val = int(_target)
self.spawn(self._set_color_temp,val)
def on_properties(self,props):
self.debug_properties(props)
......@@ -148,8 +175,8 @@ class RGBW(YeelightDev):
# color mode ?
mode = props.get('color_mode',None)
if mode:
if mode == '2' : attrs['mode'] = 0 #white
if mode == '1' : attrs['mode'] = 1 #color
if mode == '2' : attrs['mode'] = 'white'
if mode == '1' : attrs['mode'] = 'color'
# white temp
ct = props.get('ct',None)
if ct:
......@@ -157,28 +184,32 @@ class RGBW(YeelightDev):
# dimmer ?
bright = props.get('current_brightness',None)
if bright:
attrs['dimmer'] = int(bright)
#===================================================
# Yeelight API
#===================================================
@tenacity.retry(stop=TENACITY_RETRY)
def _dim(self,val):
self.bulb.turn_on()
self.bulb.set_brightness(val)
self._update_properties()
@tenacity.retry(stop=TENACITY_RETRY)
def _set_color_temp(self,val):
self.bulb.turn_on()
self.bulb.set_color_temp(val)
self._update_properties()
@tenacity.retry(stop=TENACITY_RETRY)
def _set_color(self,r,g,b):
self.bulb.turn_on()
self.bulb.duration = 5000
self.bulb.set_rgb(r,g,b)
self._update_properties()
attrs['brightness'] = int(bright)
hsv = list(attrs['hsv'])
hsv[2] = int(bright)/100.0
attrs['hsv'] = hsv
# colors stuff
# sat ?
sat = props.get('sat',None)
if sat:
hsv = attrs['hsv']
hsv[1] = (int(sat) / 100.0)
attrs['hsv']=list(hsv)
hue = props.get('hue',None)
if hue:
hsv = list(attrs['hsv'])
hsv[0] = int(hue)
attrs['hsv']=hsv
# flowing ?
flowing = props.get('flowing','0')
if flowing:
# On color change, the bulb enter in flowing mode. hsv is in proprerties only at the end of the flow
# so we schedule a periodic get_propverties. We
if flowing == '1' and self.flowing_timer == None:
# call get_properties every 0.4 sec, and max 100 times
self.flowing_timer = self.dev.engine.add_timer(self.get_properties,0.4,100)
if flowing == '0' and self.flowing_timer != None:
self.dev.engine.remove_timer(self.flowing_timer)
self.flowing_timer = None
self.get_properties()
......@@ -21,6 +21,7 @@ class GW(object):
atexit.register(self._exit)
self.config()
self.setup()
self.refresh()
self.engine.add_timer(self.refresh,60)
def config(self):
......@@ -52,7 +53,7 @@ class GW(object):
def setup(self):
logger.info("Searching for bulbs")
logger.info("Loading bulbs")
cfg = self.cfg['devices']
for k in cfg:
tmp = cfg.get(k,None)
......@@ -63,7 +64,6 @@ class GW(object):
addr = tools.get_random_uuid()
cfg[k['ip']] = {'addr':str(addr)}
bulb = yeelight.Bulb(k)
#dev = devices.RGBW(bulb,addr)
dev = devices.RGBW(bulb,addr)
self.devices.append(dev)
self.engine.add_device(dev.dev)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment