-
-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Add support for P5 FutureNow light platform #15662
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
Changes from 7 commits
f729469
b24a1fe
e533596
46b2d1b
645e46e
d4f543d
5b537f7
20bc336
6b950fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| """ | ||
| Support for FutureNow Ethernet unit outputs as Lights. | ||
|
|
||
| For more details about this platform, please refer to the documentation at | ||
| https://home-assistant.io/components/light.futurenow/ | ||
| """ | ||
|
|
||
| import logging | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.const import ( | ||
| CONF_NAME, CONF_HOST, CONF_PORT, CONF_DEVICES) | ||
| from homeassistant.components.light import ( | ||
| ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light, | ||
| PLATFORM_SCHEMA) | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| REQUIREMENTS = ['pyfnip==0.1'] | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| CONF_DRIVER = 'driver' | ||
| CONF_DRIVER_FNIP6X10AD = 'FNIP6x10ad' | ||
| CONF_DRIVER_FNIP8X10A = 'FNIP8x10a' | ||
| CONF_DRIVER_TYPES = [CONF_DRIVER_FNIP6X10AD, CONF_DRIVER_FNIP8X10A] | ||
|
|
||
| DEVICE_SCHEMA = vol.Schema({ | ||
| vol.Required(CONF_NAME): cv.string, | ||
| vol.Optional('dimmable', default=False): cv.boolean, | ||
| }) | ||
|
|
||
| PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||
| vol.Required(CONF_DRIVER): vol.In(CONF_DRIVER_TYPES), | ||
| vol.Required(CONF_HOST): cv.string, | ||
| vol.Required(CONF_PORT): cv.port, | ||
| vol.Required(CONF_DEVICES): {cv.string: DEVICE_SCHEMA}, | ||
| }) | ||
|
|
||
|
|
||
| def setup_platform(hass, config, add_devices, discovery_info=None): | ||
| """Set up the light platform for each FutureNow unit.""" | ||
| lights = [] | ||
| for channel, device_config in config[CONF_DEVICES].items(): | ||
| device = {} | ||
| device['name'] = device_config[CONF_NAME] | ||
| device['dimmable'] = device_config['dimmable'] | ||
| device['channel'] = channel | ||
| device['driver'] = config[CONF_DRIVER] | ||
| device['host'] = config[CONF_HOST] | ||
| device['port'] = config[CONF_PORT] | ||
| lights.append(FutureNowLight(device)) | ||
|
|
||
| add_devices(lights, True) | ||
|
|
||
|
|
||
| def to_futurenow_level(level): | ||
| """Convert the given HASS light level (0-255) to FutureNow (0-100).""" | ||
| return int((level * 100) / 255) | ||
|
|
||
|
|
||
| def to_hass_level(level): | ||
| """Convert the given FutureNow (0-100) light level to HASS (0-255).""" | ||
| return int((level * 255) / 100) | ||
|
|
||
|
|
||
| class FutureNowLight(Light): | ||
| """Representation of an FutureNow light.""" | ||
|
|
||
| def __init__(self, device): | ||
| """Initialize the light.""" | ||
| import pyfnip | ||
|
|
||
| self._name = device['name'] | ||
| self._dimmable = device['dimmable'] | ||
| self._channel = device['channel'] | ||
| self._brightness = None | ||
| self._state = None | ||
| self._skip_update = False | ||
|
|
||
| if device['driver'] == CONF_DRIVER_FNIP6X10AD: | ||
| self._light = pyfnip.FNIP6x2adOutput(device['host'], | ||
| device['port'], | ||
| self._channel) | ||
| if device['driver'] == CONF_DRIVER_FNIP8X10A: | ||
| self._light = pyfnip.FNIP8x10aOutput(device['host'], | ||
| device['port'], | ||
| self._channel) | ||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the device if any.""" | ||
| return self._name | ||
|
|
||
| @property | ||
| def is_on(self): | ||
| """Return true if device is on.""" | ||
| return self._state | ||
|
|
||
| @property | ||
| def brightness(self): | ||
| """Return the brightness of this light between 0..255.""" | ||
| return self._brightness | ||
|
|
||
| @property | ||
| def supported_features(self): | ||
| """Flag supported features.""" | ||
| if self._dimmable: | ||
| return SUPPORT_BRIGHTNESS | ||
| return 0 | ||
|
|
||
| def turn_on(self, **kwargs): | ||
| """Turn the light on.""" | ||
| level = kwargs.get(ATTR_BRIGHTNESS, 255) if self._dimmable else 255 | ||
| self._light.turn_on(to_futurenow_level(level)) | ||
| self._brightness = level | ||
| self._state = True | ||
| self._skip_update = True | ||
|
|
||
| def turn_off(self, **kwargs): | ||
| """Turn the light off.""" | ||
| self._light.turn_off() | ||
| self._brightness = 0 | ||
| self._state = False | ||
| self._skip_update = True | ||
|
|
||
| def update(self): | ||
| """Fetch new state data for this light.""" | ||
| if self._skip_update: | ||
| self._skip_update = False | ||
| return | ||
|
|
||
| state = int(self._light.is_on()) | ||
| if state: | ||
| self._state = True | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we can simplify to: self._state = bool(state)And then we can remove the if/else block.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for a great suggestion, it indeed seems to work! My initial thinking was probably over-complex, given that the two different FutureNow units return their state a bit differently and I wanted to use same code for all unit types when possible. Returned state can be:
|
||
| self._brightness = to_hass_level(state) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should work both when state is 0 and above 0. We can move it out of the |
||
| else: | ||
| if self._dimmable: | ||
| self._brightness = 0 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need this case. |
||
| self._state = False | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a blank line between standard library and 3rd party imports.