Skip to content

Commit

Permalink
Support transition for zigbee bulbs
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed Jan 9, 2021
1 parent e912d90 commit 15ede8d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 11 deletions.
21 changes: 21 additions & 0 deletions custom_components/xiaomi_gateway3/core/gateway3.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ def get_gateway_info(self):
payload = json.dumps(payload, separators=(',', ':'))
self.mqtt.publish(self.gw_topic + 'commands', payload)

def send_zigbee_cli(self, commands: list):
payload = {'commands': [{'commandcli': cmd} for cmd in commands]}
payload = json.dumps(payload, separators=(',', ':'))
self.mqtt.publish(self.gw_topic + 'commands', payload)

def _process_gateway_info(self):
self.debug("Update parent info table")

Expand Down Expand Up @@ -489,6 +494,19 @@ def _get_devices(self, shell: TelnetShell):

# 2. Read zigbee devices
if not self.options.get('zha'):
# read Silicon devices DB
nwks = {}
try:
raw = shell.read_file('/data/silicon_zigbee_host/devices.txt')
raw = raw.decode().split(' ')
for i in range(0, len(raw) - 1, 32):
ieee = reversed(raw[i + 3:i + 11])
ieee = ''.join(f"{i:>02s}" for i in ieee)
nwks[ieee] = f"{raw[i]:>04s}"
except:
_LOGGER.exception("Can't read Silicon devices DB")

# read Xiaomi devices DB
raw = shell.read_file('/data/zigbee_gw/' + self.ver_zigbee_db,
as_base64=True)
if raw.startswith(b'unqlite'):
Expand Down Expand Up @@ -519,9 +537,12 @@ def _get_devices(self, shell: TelnetShell):
if p[1] is not None
}

ieee = f"{data[did + '.mac']:>016s}"
device = {
'did': did,
'mac': '0x' + data[did + '.mac'],
'ieee': ieee,
'nwk': nwks.get(ieee),
'model': data[did + '.model'],
'type': 'zigbee',
'zb_ver': data[did + '.version'],
Expand Down
68 changes: 57 additions & 11 deletions custom_components/xiaomi_gateway3/light.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import logging

from homeassistant.components.light import LightEntity, SUPPORT_BRIGHTNESS, \
ATTR_BRIGHTNESS, SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP
ATTR_BRIGHTNESS, SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP, ATTR_TRANSITION
from homeassistant.config import DATA_CUSTOMIZE
from homeassistant.util import color

from . import DOMAIN, Gateway3Device
from .core.gateway3 import Gateway3

_LOGGER = logging.getLogger(__name__)

CONF_DEFAULT_TRANSITION = 'default_transition'


async def async_setup_entry(hass, config_entry, async_add_entities):
def setup(gateway: Gateway3, device: dict, attr: str):
Expand Down Expand Up @@ -47,25 +50,52 @@ def color_temp(self):

@property
def supported_features(self):
"""Flag supported features."""
features = 0
if self._brightness is not None:
features |= SUPPORT_BRIGHTNESS
if self._color_temp is not None:
features |= SUPPORT_COLOR_TEMP
return features
return SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP

def update(self, data: dict = None):
if self._attr in data:
self._state = bool(data[self._attr])
# sometimes brightness and color_temp stored as string in Xiaomi DB
if 'brightness' in data:
self._brightness = data['brightness'] / 100.0 * 255.0
self._brightness = int(data['brightness']) / 100.0 * 255.0
if 'color_temp' in data:
self._color_temp = data['color_temp']
self._color_temp = int(data['color_temp'])

self.async_write_ha_state()

def turn_on(self, **kwargs):
if ATTR_TRANSITION not in kwargs:
custom = self.hass.data[DATA_CUSTOMIZE].get(self.entity_id)
if CONF_DEFAULT_TRANSITION in custom:
kwargs[ATTR_TRANSITION] = custom[CONF_DEFAULT_TRANSITION]

# transition works only with raw zigbee commands
if ATTR_TRANSITION in kwargs:
# is the amount of time, in tenths of a second
tr = int(kwargs[ATTR_TRANSITION] * 10.0)
commands = []

if ATTR_COLOR_TEMP in kwargs:
ct = int(kwargs[ATTR_COLOR_TEMP])
commands += [
f"zcl color-control movetocolortemp {ct} {tr} 0 0",
f"send 0x{self.device['nwk']} 1 1"
]

# if only turn_on with transition restore last brightness
if ATTR_BRIGHTNESS not in kwargs and not commands:
kwargs[ATTR_BRIGHTNESS] = self.brightness or 255

if ATTR_BRIGHTNESS in kwargs:
br = int(kwargs[ATTR_BRIGHTNESS])
commands += [
f"zcl level-control o-mv-to-level {br} {tr}",
f"send 0x{self.device['nwk']} 1 1"
]

self.gw.send_zigbee_cli(commands)
return

payload = {}

if ATTR_BRIGHTNESS in kwargs:
Expand All @@ -80,7 +110,23 @@ def turn_on(self, **kwargs):

self.gw.send(self.device, payload)

def turn_off(self):
def turn_off(self, **kwargs):
if ATTR_TRANSITION not in kwargs:
custom = self.hass.data[DATA_CUSTOMIZE].get(self.entity_id)
if CONF_DEFAULT_TRANSITION in custom:
kwargs[ATTR_TRANSITION] = custom[CONF_DEFAULT_TRANSITION]

# transition works only with raw zigbee commands
if ATTR_TRANSITION in kwargs:
# is the amount of time, in tenths of a second
tr = int(kwargs[ATTR_TRANSITION] * 10.0)
commands = [
f"zcl level-control o-mv-to-level 0 {tr}",
f"send 0x{self.device['nwk']} 1 1"
]
self.gw.send_zigbee_cli(commands)
return

self.gw.send(self.device, {self._attr: 0})


Expand Down

0 comments on commit 15ede8d

Please sign in to comment.