Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improves light support #155

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 95 additions & 49 deletions custom_components/smartir/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@
CMD_POWER_ON = "on"
CMD_POWER_OFF = "off"
CMD_NIGHTLIGHT = "night"
CMD_COLORTEMPERATURE = "colorTemperature"
CMD_BRIGHTNESS = "brightness"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_DEVICE_CODE): cv.positive_int,
vol.Required(CONF_CONTROLLER_DATA): get_controller_schema(vol, cv),
vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): cv.string,
vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): cv.positive_float,
vol.Optional(CONF_POWER_SENSOR): cv.entity_id,
vol.Optional(
CONF_POWER_SENSOR_DELAY, default=DEFAULT_POWER_SENSOR_DELAY
Expand Down Expand Up @@ -105,13 +107,13 @@ def __init__(self, hass, config, device_data):
self._colortemps = device_data["colorTemperature"]
self._commands = device_data["commands"]

if (
if CMD_COLORTEMPERATURE in self._commands or (
CMD_COLORMODE_COLDER in self._commands
and CMD_COLORMODE_WARMER in self._commands
):
self._colortemp = self.max_color_temp_kelvin

if CMD_NIGHTLIGHT in self._commands or (
if CMD_NIGHTLIGHT in self._commands or CMD_BRIGHTNESS in self._commands or (
CMD_BRIGHTNESS_INCREASE in self._commands
and CMD_BRIGHTNESS_DECREASE in self._commands
):
Expand Down Expand Up @@ -221,8 +223,20 @@ async def async_turn_on(self, **params):
# Turn the light on if off
if self._state != STATE_ON and not self._on_by_remote:
self._state = STATE_ON
did_something = True
await self.send_command(CMD_POWER_ON)
if CMD_POWER_ON in self._commands:
did_something = True
await self.send_command(CMD_POWER_ON)
else:
if ATTR_COLOR_TEMP_KELVIN not in params:
_LOGGER.debug(
f"No power on command found, setting last color {self._colortemp}K"
)
params[ATTR_COLOR_TEMP_KELVIN] = self._colortemp
if ATTR_BRIGHTNESS not in params:
_LOGGER.debug(
f"No power on command found, setting last brightness {self._brightness}"
)
params[ATTR_BRIGHTNESS] = self._brightness

if (
ATTR_COLOR_TEMP_KELVIN in params
Expand All @@ -231,26 +245,40 @@ async def async_turn_on(self, **params):
target = params.get(ATTR_COLOR_TEMP_KELVIN)
old_color_temp = DeviceData.closest_match(self._colortemp, self._colortemps)
new_color_temp = DeviceData.closest_match(target, self._colortemps)
_LOGGER.debug(
f"Changing color temp from {self._colortemp}K step {old_color_temp} to {target}K step {new_color_temp}"
)

steps = new_color_temp - old_color_temp
did_something = True
if steps < 0:
cmd = CMD_COLORMODE_WARMER
steps = abs(steps)
else:
cmd = CMD_COLORMODE_COLDER

if steps > 0 and cmd:
# If we are heading for the highest or lowest value,
# take the opportunity to resync by issuing enough
# commands to go the full range.
if new_color_temp == len(self._colortemps) - 1 or new_color_temp == 0:
steps = len(self._colortemps)
final_color_temp = f"{self._colortemps[new_color_temp]}"
if (
CMD_COLORTEMPERATURE in self._commands
and isinstance(self._commands[CMD_COLORTEMPERATURE], dict)
and final_color_temp in self._commands[CMD_COLORTEMPERATURE]
):
_LOGGER.debug(
f"Changing color temp from {self._colortemp}K to {target}K using found remote command for {final_color_temp}K"
)
did_something = True
found_command = self._commands[CMD_COLORTEMPERATURE][final_color_temp]
self._colortemp = self._colortemps[new_color_temp]
await self.send_command(cmd, steps)
await self.send_remote_command(found_command)
else:
_LOGGER.debug(
f"Changing color temp from {self._colortemp}K step {old_color_temp} to {target}K step {new_color_temp}"
)

steps = new_color_temp - old_color_temp
if steps < 0:
cmd = CMD_COLORMODE_WARMER
steps = abs(steps)
else:
cmd = CMD_COLORMODE_COLDER

if steps > 0 and cmd:
# If we are heading for the highest or lowest value,
# take the opportunity to resync by issuing enough
# commands to go the full range.
if new_color_temp == len(self._colortemps) - 1 or new_color_temp == 0:
steps = len(self._colortemps)
did_something = True
self._colortemp = self._colortemps[new_color_temp]
await self.send_command(cmd, steps)

if ATTR_BRIGHTNESS in params and self._support_brightness:
# before checking the supported brightnesses, make a special case
Expand All @@ -266,30 +294,43 @@ async def async_turn_on(self, **params):
old_brightness = DeviceData.closest_match(
self._brightness, self._brightnesses
)
new_brightness = DeviceData.closest_match(target, self._brightnesses)
did_something = True
_LOGGER.debug(
f"Changing brightness from {self._brightness} step {old_brightness} to {target} step {new_brightness}"
)
steps = new_brightness - old_brightness
if steps < 0:
cmd = CMD_BRIGHTNESS_DECREASE
steps = abs(steps)
else:
cmd = CMD_BRIGHTNESS_INCREASE

if steps > 0 and cmd:
# If we are heading for the highest or lowest value,
# take the opportunity to resync by issuing enough
# commands to go the full range.
if (
new_brightness == len(self._brightnesses) - 1
or new_brightness == 0
):
steps = len(self._colortemps)
new_brightness = DeviceData.closest_match(target, self._brightnesses)
final_brightness = f"{self._brightnesses[new_brightness]}"
if (
CMD_BRIGHTNESS in self._commands
and isinstance(self._commands[CMD_BRIGHTNESS], dict)
and final_brightness in self._commands[CMD_BRIGHTNESS]
):
_LOGGER.debug(
f"Changing brightness from {self._brightness} to {target} using found remote command for {final_brightness}"
)
did_something = True
found_command = self._commands[CMD_BRIGHTNESS][final_brightness]
self._brightness = self._brightnesses[new_brightness]
await self.send_command(cmd, steps)
await self.send_remote_command(found_command)
else:
_LOGGER.debug(
f"Changing brightness from {self._brightness} step {old_brightness} to {target} step {new_brightness}"
)
steps = new_brightness - old_brightness
if steps < 0:
cmd = CMD_BRIGHTNESS_DECREASE
steps = abs(steps)
else:
cmd = CMD_BRIGHTNESS_INCREASE

if steps > 0 and cmd:
# If we are heading for the highest or lowest value,
# take the opportunity to resync by issuing enough
# commands to go the full range.
if (
new_brightness == len(self._brightnesses) - 1
or new_brightness == 0
):
steps = len(self._brightnesses)
did_something = True
self._brightness = self._brightnesses[new_brightness]
await self.send_command(cmd, steps)

# If we did nothing above, and the light is not detected as on
# already issue the on command, even though we think the light
Expand All @@ -304,9 +345,10 @@ async def async_turn_on(self, **params):
self.async_write_ha_state()

async def async_turn_off(self):
self._state = STATE_OFF
await self.send_command(CMD_POWER_OFF)
self.async_write_ha_state()
if self._state != STATE_OFF:
self._state = STATE_OFF
await self.send_command(CMD_POWER_OFF)
self.async_write_ha_state()

async def async_toggle(self):
await (self.async_turn_on() if not self.is_on else self.async_turn_off())
Expand All @@ -317,11 +359,15 @@ async def send_command(self, cmd, count=1):
return
_LOGGER.debug(f"Sending {cmd} remote command {count} times.")
remote_cmd = self._commands.get(cmd)
await self.send_remote_command(remote_cmd, count)

async def send_remote_command(self, remote_cmd, count=1):
async with self._temp_lock:
self._on_by_remote = False
try:
for _ in range(count):
await self._controller.send(remote_cmd)
await asyncio.sleep(self._delay)
except Exception as e:
_LOGGER.exception(e)

Expand Down