Skip to content

Commit

Permalink
Merge remote-tracking branch 'thomasadelhardt/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed Feb 14, 2021
2 parents cfc8a29 + 44126e9 commit fba1eb5
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 1 deletion.
138 changes: 137 additions & 1 deletion custom_components/sonoff/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ async def async_setup_platform(hass, config, add_entities,
add_entities([SonoffDiffuserLight(registry, deviceid)])
elif uiid == 57:
add_entities([Sonoff57(registry, deviceid)])
elif uiid == 103:
add_entities([Sonoff103(registry, deviceid)])
elif uiid == 104:
add_entities([SonoffB05(registry, deviceid)])
elif channels and len(channels) >= 2:
Expand Down Expand Up @@ -337,7 +339,6 @@ class EWeLinkLightGroup(SonoffD1):
"""Differs from the usual switch by brightness adjustment. Is logical
use only for two or more channels. Able to remember brightness on moment
off.
The sequence of channels is important. The first channels will be turned on
at low brightness.
"""
Expand Down Expand Up @@ -508,6 +509,141 @@ async def async_turn_off(self, **kwargs) -> None:
await self.registry.send(self.deviceid, {'state': 'off'})


SONOFF103_MODES = {
'white': 'Custom',
'nightLight': 'Night',
'read': 'Reading',
'computer': 'Work',
'bright': 'Bright'
}

SONOFF103_MODE_PAYLOADS = {
'nightLight': {'br': 5, 'ct': 0},
'read': {'br': 50, 'ct': 0},
'computer': {'br': 20, 'ct': 255},
'bright': {'br': 100, 'ct': 255},
}


class Sonoff103(EWeLinkToggle):
_brightness = None
_mode = None
_temp = None

_min_mireds = None
_max_mireds = None

async def async_added_to_hass(self) -> None:
await super().async_added_to_hass()

device: dict = self.registry.devices[self.deviceid]
model = device.get('productModel')
if model == 'B02-F-ST64':
self._min_mireds = int(1000000 / 5000)
self._max_mireds = int(1000000 / 1800)
elif model == 'QMS-2C-CW':
self._min_mireds = int(1000000 / 6500)
self._max_mireds = int(1000000 / 2700)
else: # FS-1, B02-F-A60 and other
self._min_mireds = int(1000000 / 6500)
self._max_mireds = int(1000000 / 2200)

def _update_handler(self, state: dict, attrs: dict):
self._attrs.update(attrs)

if 'switch' in state:
self._is_on = state['switch'] == 'on'

if 'ltype' in state:
self._mode = state['ltype']
state = state[self._mode]

if 'br' in state:
# 1..100 => 1..255
br = state['br']
self._brightness = \
round(1.0 + (br - 1.0) / (100.0 - 1.0) * 254.0)

if 'ct' in state:
# 0..255 => Mireds..
ct = state['ct']
self._temp = round(self._min_mireds - ct / 255.0 *
(self._max_mireds - self._min_mireds))

self.async_write_ha_state()

@property
def brightness(self):
"""Return the brightness of this light between 0..255."""
return self._brightness

@property
def color_temp(self):
"""Return the CT color value in mireds."""
return self._temp

@property
def effect(self):
"""Return the current effect."""
return SONOFF103_MODES[self._mode]

@property
def effect_list(self):
"""Return the list of supported effects."""
return list(SONOFF103_MODES.values())

@property
def is_on(self):
"""Returns if the light entity is on or not."""
return self._is_on

@property
def supported_features(self):
return SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT

@property
def capability_attributes(self):
return {
ATTR_EFFECT_LIST: self.effect_list,
ATTR_MIN_MIREDS: round(self._min_mireds),
ATTR_MAX_MIREDS: round(self._max_mireds)
}

@property
def state_attributes(self):
return {
**self._attrs,
ATTR_BRIGHTNESS: self.brightness,
ATTR_COLOR_TEMP: self._temp,
ATTR_EFFECT: self.effect
}

async def async_turn_on(self, **kwargs) -> None:
payload = {}

if ATTR_EFFECT in kwargs:
mode = next(k for k, v in SONOFF103_MODES.items()
if v == kwargs[ATTR_EFFECT])
payload['ltype'] = mode
if mode in SONOFF103_MODE_PAYLOADS:
payload.update({mode: SONOFF103_MODE_PAYLOADS[mode]})
else:
mode = self._mode

if mode == 'white':
br = kwargs.get(ATTR_BRIGHTNESS) or self._brightness or 1
ct = kwargs.get(ATTR_COLOR_TEMP) or self._temp or 153

payload['ltype'] = mode
payload[mode] = {
'br': int(round((br - 1.0) * (100.0 - 1.0) / 254.0 + 1.0)),
'ct': int(round((self._max_mireds - ct) /
(self._max_mireds - self._min_mireds) * 255.0))
}

await self.registry.send(self.deviceid, payload)


B05_MODES = {
'color': 'Color',
'white': 'White',
Expand Down
1 change: 1 addition & 0 deletions custom_components/sonoff/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def init_device_class(default_class: str = 'switch'):
83: switch3,
84: switch4,
102: 'binary_sensor', # Sonoff DW2 Door/Window sensor
103: 'light', # CCT bulb
104: 'light', # RGB+CCT color bulb
107: switchx,
1000: 'sensor', # zigbee_ON_OFF_SWITCH_1000
Expand Down

0 comments on commit fba1eb5

Please sign in to comment.