class WOLSwitch(SwitchDevice): """Representation of a wake on lan switch.""" def __init__(self, hass, name, host, mac_address, off_action, broadcast_address): """Initialize the WOL switch.""" import wakeonlan self._hass = hass self._name = name self._host = host self._mac_address = mac_address self._broadcast_address = broadcast_address self._off_script = Script(hass, off_action) if off_action else None self._state = False self._wol = wakeonlan @property def should_poll(self): """Return the polling state.""" return True @property def is_on(self): """Return true if switch is on.""" return self._state @property def name(self): """Return the name of the switch.""" return self._name def turn_on(self, **kwargs): """Turn the device on.""" if self._broadcast_address: self._wol.send_magic_packet(self._mac_address, ip_address=self._broadcast_address) else: self._wol.send_magic_packet(self._mac_address) def turn_off(self, **kwargs): """Turn the device off if an off action is present.""" if self._off_script is not None: self._off_script.run() def update(self): """Check if device is on and update the state.""" if platform.system().lower() == 'windows': ping_cmd = [ 'ping', '-n', '1', '-w', str(DEFAULT_PING_TIMEOUT * 1000), str(self._host) ] else: ping_cmd = [ 'ping', '-c', '1', '-W', str(DEFAULT_PING_TIMEOUT), str(self._host) ] status = sp.call(ping_cmd, stdout=sp.DEVNULL, stderr=sp.DEVNULL) self._state = not bool(status)
class WOLSwitch(SwitchDevice): """Representation of a wake on lan switch.""" def __init__(self, hass, name, host, mac_address, off_action, broadcast_address): """Initialize the WOL switch.""" from wakeonlan import wol self._hass = hass self._name = name self._host = host self._mac_address = mac_address self._broadcast_address = broadcast_address self._off_script = Script(hass, off_action) if off_action else None self._state = False self._wol = wol self.update() @property def should_poll(self): """Return the polling state.""" return True @property def is_on(self): """Return true if switch is on.""" return self._state @property def name(self): """Return the name of the switch.""" return self._name def turn_on(self): """Turn the device on.""" if self._broadcast_address: self._wol.send_magic_packet( self._mac_address, ip_address=self._broadcast_address) else: self._wol.send_magic_packet(self._mac_address) def turn_off(self): """Turn the device off if an off action is present.""" if self._off_script is not None: self._off_script.run() def update(self): """Check if device is on and update the state.""" if platform.system().lower() == 'windows': ping_cmd = ['ping', '-n', '1', '-w', str(DEFAULT_PING_TIMEOUT * 1000), str(self._host)] else: ping_cmd = ['ping', '-c', '1', '-W', str(DEFAULT_PING_TIMEOUT), str(self._host)] status = sp.call(ping_cmd, stdout=sp.DEVNULL, stderr=sp.DEVNULL) self._state = not bool(status)
def invoke_current_scene(self): current_scene = self.get_current_scene() _LOGGER.debug(f'Invoking script of {current_scene}') if self._scenes is not None and current_scene in self._scenes: scene = self._scenes[current_scene] if CONF_SCENE_SCRIPT in scene: scene_script = scene[CONF_SCENE_SCRIPT] if scene_script is not None: script_invoker = Script(self._hass, scene_script) script_invoker.run()
def restore(self, entity_id, restore_script, delete): if entity_id not in self._entities_db: return old = self._entities_db[entity_id] variables = SaverEntity.convert_to_variables(old) if delete: self._entities_db.pop(entity_id) script = Script(self.hass, restore_script, self.name, DOMAIN, script_mode=SCRIPT_MODE_PARALLEL) script.run(variables=variables, context=Context()) self.schedule_update_ha_state()
def execute(self, script): script = Script(self.hass, script, self.name, DOMAIN, script_mode=SCRIPT_MODE_PARALLEL) variables = {} variables.update(self._variables_db) for entity_id in self._entities_db: variables.update( SaverEntity.convert_to_variables(self._entities_db[entity_id], entity_id)) script.run(variables=variables, context=Context()) self.schedule_update_ha_state()
class WOLSwitch(SwitchDevice): """Representation of a wake on lan switch.""" def __init__(self, hass, name, host, mac_address, off_action): """Initialize the WOL switch.""" from wakeonlan import wol self._hass = hass self._name = name self._host = host self._mac_address = mac_address self._off_script = Script(hass, off_action) if off_action else None self._state = False self._wol = wol self.update() @property def should_poll(self): """Poll for status regularly.""" return True @property def is_on(self): """Return true if switch is on.""" return self._state @property def name(self): """The name of the switch.""" return self._name def turn_on(self): """Turn the device on.""" self._wol.send_magic_packet(self._mac_address) def turn_off(self): """Turn the device off if an off action is present.""" if self._off_script is not None: self._off_script.run() def update(self): """Check if device is on and update the state.""" if platform.system().lower() == 'windows': ping_cmd = 'ping -n 1 -w {} {}'.format(DEFAULT_PING_TIMEOUT * 1000, self._host) else: ping_cmd = 'ping -c 1 -W {} {}'.format(DEFAULT_PING_TIMEOUT, self._host) status = sp.getstatusoutput(ping_cmd)[0] self._state = not bool(status)
class WOLSwitch(SwitchDevice): """Representation of a wake on lan switch.""" def __init__(self, hass, name, host, mac_address, off_action): """Initialize the WOL switch.""" from wakeonlan import wol self._hass = hass self._name = name self._host = host self._mac_address = mac_address self._off_script = Script(hass, off_action) if off_action else None self._state = False self._wol = wol self.update() @property def should_poll(self): """Poll for status regularly.""" return True @property def is_on(self): """Return true if switch is on.""" return self._state @property def name(self): """The name of the switch.""" return self._name def turn_on(self): """Turn the device on.""" self._wol.send_magic_packet(self._mac_address) def turn_off(self): """Turn the device off if an off action is present.""" if self._off_script is not None: self._off_script.run() def update(self): """Check if device is on and update the state.""" if platform.system().lower() == "windows": ping_cmd = "ping -n 1 -w {} {}".format(DEFAULT_PING_TIMEOUT * 1000, self._host) else: ping_cmd = "ping -c 1 -W {} {}".format(DEFAULT_PING_TIMEOUT, self._host) status = sp.getstatusoutput(ping_cmd)[0] self._state = not bool(status)
class ScriptEntity(ToggleEntity): """Representation of a script entity.""" # pylint: disable=too-many-instance-attributes def __init__(self, hass, object_id, name, sequence): """Initialize the script.""" self.entity_id = ENTITY_ID_FORMAT.format(object_id) self.script = Script(hass, sequence, name, self.update_ha_state) @property def should_poll(self): """No polling needed.""" return False @property def name(self): """Return the name of the entity.""" return self.script.name @property def state_attributes(self): """Return the state attributes.""" attrs = {} if self.script.can_cancel: attrs[ATTR_CAN_CANCEL] = self.script.can_cancel if self.script.last_action: attrs[ATTR_LAST_ACTION] = self.script.last_action return attrs @property def is_on(self): """Return true if script is on.""" return self.script.is_running def turn_on(self, **kwargs): """Turn the entity on.""" self.script.run(kwargs.get(ATTR_VARIABLES)) def turn_off(self, **kwargs): """Turn script off.""" self.script.stop()
class ScriptEntity(ToggleEntity): """Representation of a script entity.""" # pylint: disable=too-many-instance-attributes def __init__(self, hass, object_id, name, sequence): """Initialize the script.""" self.entity_id = ENTITY_ID_FORMAT.format(object_id) self.script = Script(hass, sequence, name, self.async_update_ha_state) @property def should_poll(self): """No polling needed.""" return False @property def name(self): """Return the name of the entity.""" return self.script.name @property def state_attributes(self): """Return the state attributes.""" attrs = {} if self.script.can_cancel: attrs[ATTR_CAN_CANCEL] = self.script.can_cancel if self.script.last_action: attrs[ATTR_LAST_ACTION] = self.script.last_action return attrs @property def is_on(self): """Return true if script is on.""" return self.script.is_running def turn_on(self, **kwargs): """Turn the entity on.""" self.script.run(kwargs.get(ATTR_VARIABLES)) def turn_off(self, **kwargs): """Turn script off.""" self.script.stop()
class Instruction: def __init__(self, hass, bot, command): self.hass = hass self.bot = bot self.script = None self.response = None self.command = command[COMMAND] _script = command.get(SCRIPT, None) if _script is not None: self.script = Script(hass, _script) _response = command.get(RESPONSE, None) if _response is not None: self.response = {RESPONSE_TEXT: _response.get(RESPONSE_TEXT, None)} _keyboard = _response.get(RESPONSE_KEYBOARD, None) if _keyboard: self.response[RESPONSE_KEYBOARD] = { "keyboard": [], "resize_keyboard": True, "one_time_keyboard": True } for _key in _keyboard: self.response[RESPONSE_KEYBOARD]["keyboard"].append([{ "text": _key }]) else: self.response[RESPONSE_KEYBOARD] = None def execute(self, chat_id): if self.script: self.script.run() if self.response: self.bot.sendMessage(chat_id, self.response[RESPONSE_TEXT], parse_mode="Markdown", reply_markup=self.response[RESPONSE_KEYBOARD])
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # Assume that the TV is not muted self._muted = False # Assume that the TV is in Play mode self._playing = True self._volume = 0 self._current_source = None self._current_source_id = None self._state = STATE_UNKNOWN self._source_list = {} self._app_list = {} self._channel = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (STATE_UNKNOWN, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (not conf_sources or app['id'] in conf_sources or any(word in app['title'] for word in conf_sources) or any(word in app['id'] for word in conf_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): if source['id'] == self._current_source_id: self._current_source = source['label'] self._source_list[source['label']] = source elif (not conf_sources or source['label'] in conf_sources or any(source['label'].find(word) != -1 for word in conf_sources)): self._source_list[source['label']] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @property def name(self): """Return the name of the device.""" return self._name @property def state(self): """Return the state of the device.""" return self._state @property def is_volume_muted(self): """Boolean if volume is currently muted.""" return self._muted @property def volume_level(self): """Volume level of the media player (0..1).""" return self._volume / 100.0 @property def source(self): """Return the current input source.""" return self._current_source @property def source_list(self): """List of available input sources.""" return sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ('channelName' in self._channel): return self._channel['channelName'] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]['largeIcon'] if not icon.startswith('http'): icon = self._app_list[self._current_source_id]['icon'] return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: return SUPPORT_WEBOSTV | SUPPORT_TURN_ON return SUPPORT_WEBOSTV def turn_off(self): """Turn off media player.""" from websockets.exceptions import ConnectionClosed self._state = STATE_OFF try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() def volume_up(self): """Volume up the media player.""" self._client.volume_up() def volume_down(self): """Volume down media player.""" self._client.volume_down() def set_volume_level(self, volume): """Set volume level, range 0..1.""" tv_volume = volume * 100 self._client.set_volume(tv_volume) def mute_volume(self, mute): """Send mute command.""" self._muted = mute self._client.set_mute(mute) def media_play_pause(self): """Simulate play pause media player.""" if self._playing: self.media_pause() else: self.media_play() def select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict['id'] if source_dict.get('title'): self._current_source = source_dict['title'] self._client.launch_app(source_dict['id']) elif source_dict.get('label'): self._current_source = source_dict['label'] self._client.set_input(source_dict['id']) def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" _LOGGER.debug( "Call play media type <%s>, Id <%s>", media_type, media_id) if media_type == MEDIA_TYPE_CHANNEL: _LOGGER.debug("Searching channel...") partial_match_channel_id = None perfect_match_channel_id = None for channel in self._client.get_channels(): if media_id == channel['channelNumber']: perfect_match_channel_id = channel['channelId'] continue elif media_id.lower() == channel['channelName'].lower(): perfect_match_channel_id = channel['channelId'] continue elif media_id.lower() in channel['channelName'].lower(): partial_match_channel_id = channel['channelId'] if perfect_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with perfect match", perfect_match_channel_id) self._client.set_channel(perfect_match_channel_id) elif partial_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with partial match", partial_match_channel_id) self._client.set_channel(partial_match_channel_id) return def media_play(self): """Send play command.""" self._playing = True self._state = STATE_PLAYING self._client.play() def media_pause(self): """Send media pause command to media player.""" self._playing = False self._state = STATE_PAUSED self._client.pause() def media_next_track(self): """Send next track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_up() else: self._client.fast_forward() def media_previous_track(self): """Send the previous track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_down() else: self._client.rewind()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # Assume that the TV is not muted self._muted = False # Assume that the TV is in Play mode self._playing = True self._volume = 0 self._current_source = None self._current_source_id = None self._state = None self._source_list = {} self._app_list = {} self._channel = None self._last_icon = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (None, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app["id"]] = app if app["id"] == self._current_source_id: self._current_source = app["title"] self._source_list[app["title"]] = app elif (not conf_sources or app["id"] in conf_sources or any(word in app["title"] for word in conf_sources) or any(word in app["id"] for word in conf_sources)): self._source_list[app["title"]] = app for source in self._client.get_inputs(): if source["id"] == self._current_source_id: self._current_source = source["label"] self._source_list[source["label"]] = source elif (not conf_sources or source["label"] in conf_sources or any(source["label"].find(word) != -1 for word in conf_sources)): self._source_list[source["label"]] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @property def name(self): """Return the name of the device.""" return self._name @property def state(self): """Return the state of the device.""" return self._state @property def is_volume_muted(self): """Boolean if volume is currently muted.""" return self._muted @property def volume_level(self): """Volume level of the media player (0..1).""" return self._volume / 100.0 @property def source(self): """Return the current input source.""" return self._current_source @property def source_list(self): """List of available input sources.""" return sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ("channelName" in self._channel): return self._channel["channelName"] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]["largeIcon"] if not icon.startswith("http"): icon = self._app_list[self._current_source_id]["icon"] # 'icon' holds a URL with a transient key. Avoid unnecessary # updates by returning the same URL until the image changes. if self._last_icon and (icon.split("/")[-1] == self._last_icon.split("/")[-1]): return self._last_icon self._last_icon = icon return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: return SUPPORT_WEBOSTV | SUPPORT_TURN_ON return SUPPORT_WEBOSTV def turn_off(self): """Turn off media player.""" from websockets.exceptions import ConnectionClosed self._state = STATE_OFF try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() def volume_up(self): """Volume up the media player.""" self._client.volume_up() def volume_down(self): """Volume down media player.""" self._client.volume_down() def set_volume_level(self, volume): """Set volume level, range 0..1.""" tv_volume = volume * 100 self._client.set_volume(tv_volume) def mute_volume(self, mute): """Send mute command.""" self._muted = mute self._client.set_mute(mute) def media_play_pause(self): """Simulate play pause media player.""" if self._playing: self.media_pause() else: self.media_play() def select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict["id"] if source_dict.get("title"): self._current_source = source_dict["title"] self._client.launch_app(source_dict["id"]) elif source_dict.get("label"): self._current_source = source_dict["label"] self._client.set_input(source_dict["id"]) def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" _LOGGER.debug("Call play media type <%s>, Id <%s>", media_type, media_id) if media_type == MEDIA_TYPE_CHANNEL: _LOGGER.debug("Searching channel...") partial_match_channel_id = None perfect_match_channel_id = None for channel in self._client.get_channels(): if media_id == channel["channelNumber"]: perfect_match_channel_id = channel["channelId"] continue elif media_id.lower() == channel["channelName"].lower(): perfect_match_channel_id = channel["channelId"] continue elif media_id.lower() in channel["channelName"].lower(): partial_match_channel_id = channel["channelId"] if perfect_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with perfect match", perfect_match_channel_id, ) self._client.set_channel(perfect_match_channel_id) elif partial_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with partial match", partial_match_channel_id, ) self._client.set_channel(partial_match_channel_id) return def media_play(self): """Send play command.""" self._playing = True self._state = STATE_PLAYING self._client.play() def media_pause(self): """Send media pause command to media player.""" self._playing = False self._state = STATE_PAUSED self._client.pause() def media_next_track(self): """Send next track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_up() else: self._client.fast_forward() def media_previous_track(self): """Send the previous track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_down() else: self._client.rewind()
class GenericHumidifierEntity(HumidifierEntity, RestoreEntity): def __init__(self, hass, config): self._hass = hass self._power = False self._humidity = 0 self._mode = MODE_AUTO self._name = config.get(NAME_CONFIG, None) self._unique_id = config.get(UNIQUE_ID_CONFIG, None) self._boot_mode_tether = config.get(BOOT_MODE_TETHER_CONFIG, None) self._above_tolerance = float(config.get(ABOVE_TOLERANCE, 0)) self._below_tolerance = float(config.get(BELOW_TOLERANCE, 0)) self._first_cycle = True self._current_mode = None self._modes_script = dict() self._available_modes = [] self.__init_modes_script(config) self._init_properties(dict()) self._turn_off_action = config.get(OFF_ACTION, None) if self._turn_off_action: if isinstance(self._turn_off_action, list): self._turn_off_script = Script(self._hass, self._turn_off_action, self._unique_id, DOMAIN) else: self._turn_off_script = Script(self._hass, [self._turn_off_action], self._unique_id, DOMAIN) self._humidity_sensor = config.get(HUMIDITY_SENSOR, None) if self._humidity_sensor: async_track_state_change(self._hass, self._humidity_sensor, self._handle_humidity_state_update) def __init_modes_script(self, config): for mode in MODES: mode_action = config.get(mode, None) if not mode_action: continue if isinstance(mode_action, list): self._modes_script[mode] = Script(self._hass, mode_action, self._unique_id, DOMAIN) else: self._modes_script[mode] = Script(self._hass, [mode_action], self._unique_id, DOMAIN) self._available_modes.append(mode) if len(self._available_modes) > 1: self._supported_features = SUPPORT_MODES else: self._supported_features = 0 def _handle_humidity_state_update(self, entity_id: str, old_state: State, new_state: State) -> None: self.__handle_mode() def __handle_mode(self): if not self.is_on: return sensor_state = self._hass.states.get(self._humidity_sensor) if not sensor_state or not sensor_state.state: return sensor_value = float(sensor_state.state) if self._first_cycle: if self.target_humidity <= sensor_value: self.__turn_off() return else: if not self._first_cycle and ( self.target_humidity + self._above_tolerance) <= sensor_value: self.__turn_off() return if not self._first_cycle and ( self.target_humidity - self._below_tolerance) <= sensor_value: return self._first_cycle = False if self.mode != MODE_AUTO: self.__turn_on_mode(self.mode) elif self.mode == MODE_AUTO and not self._boot_mode_tether: self.__turn_on_mode(MODE_AUTO) elif self.mode == MODE_AUTO and self._boot_mode_tether and MODE_BOOST in self._available_modes: if self.target_humidity - sensor_value > self._boot_mode_tether: self.__turn_on_mode(MODE_BOOST) else: self.__turn_on_mode(MODE_AUTO) def __turn_on_mode(self, mode): if mode == self._current_mode: return self._modes_script[mode].run() self._current_mode = mode def __turn_off(self): if not self._turn_off_script: return self._turn_off_script.run() self._current_mode = None @property def unique_id(self) -> Optional[str]: return self._unique_id @property def name(self) -> Optional[str]: return self._name @property def device_class(self) -> Optional[str]: return DEVICE_CLASS_HUMIDIFIER @property def is_on(self) -> bool: return self._power def turn_on(self, **kwargs: Any) -> None: self._power = True self._first_cycle = True self.__handle_mode() def turn_off(self, **kwargs: Any) -> None: self._power = False self.__turn_off() @property def target_humidity(self) -> Optional[int]: return self._humidity def set_humidity(self, humidity: int) -> None: self._first_cycle = True self._humidity = humidity self.__handle_mode() @property def available_modes(self) -> Optional[List[str]]: return self._available_modes @property def mode(self) -> Optional[str]: return self._mode def set_mode(self, mode: str) -> None: self._mode = mode self.__handle_mode() @property def supported_features(self) -> Optional[int]: return self._supported_features async def async_added_to_hass(self) -> None: last_state = await self.async_get_last_state() if not last_state: return last_state_dict = last_state.as_dict().get("attributes", dict()) if last_state.state == 'off': last_state_dict["power"] = False else: last_state_dict["power"] = True self._init_properties(last_state_dict) await self.async_update_ha_state(True) def _init_properties(self, property_store): self._humidity = property_store.get("humidity", 0) self._mode = property_store.get("mode", MODE_AUTO) self._power = property_store.get("power", False)
class SwitchTemplate(SwitchDevice): """Representation of a Template switch.""" def __init__(self, hass, device_id, friendly_name, state_template, on_action, off_action, entity_ids): """Initialize the Template switch.""" self.hass = hass self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._template = state_template self._on_script = Script(hass, on_action) self._off_script = Script(hass, off_action) self._state = False @callback def template_switch_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" hass.async_add_job(self.async_update_ha_state(True)) async_track_state_change(hass, entity_ids, template_switch_state_listener) @property def name(self): """Return the name of the switch.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def should_poll(self): """No polling needed.""" return False @property def available(self): """If switch is available.""" return self._state is not None def turn_on(self, **kwargs): """Fire the on action.""" self._on_script.run() def turn_off(self, **kwargs): """Fire the off action.""" self._off_script.run() @asyncio.coroutine def async_update(self): """Update the state from the template.""" try: state = self._template.async_render().lower() if state in _VALID_STATES: self._state = state in ('true', STATE_ON) else: _LOGGER.error( 'Received invalid switch is_on state: %s. Expected: %s', state, ', '.join(_VALID_STATES)) self._state = None except TemplateError as ex: _LOGGER.error(ex) self._state = None
class SwitchTemplate(SwitchDevice): """Representation of a Template switch.""" def __init__(self, hass, device_id, friendly_name, state_template, on_action, off_action, entity_ids): """Initialize the Template switch.""" self.hass = hass self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._template = state_template self._on_script = Script(hass, on_action) self._off_script = Script(hass, off_action) self._state = False self._entities = entity_ids @asyncio.coroutine def async_added_to_hass(self): """Register callbacks.""" state = yield from async_get_last_state(self.hass, self.entity_id) if state: self._state = state.state == STATE_ON @callback def template_switch_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" self.hass.async_add_job(self.async_update_ha_state(True)) @callback def template_switch_startup(event): """Update template on startup.""" async_track_state_change( self.hass, self._entities, template_switch_state_listener) self.hass.async_add_job(self.async_update_ha_state(True)) self.hass.bus.async_listen_once( EVENT_HOMEASSISTANT_START, template_switch_startup) @property def name(self): """Return the name of the switch.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def should_poll(self): """No polling needed.""" return False @property def available(self): """If switch is available.""" return self._state is not None def turn_on(self, **kwargs): """Fire the on action.""" self._on_script.run() def turn_off(self, **kwargs): """Fire the off action.""" self._off_script.run() @asyncio.coroutine def async_update(self): """Update the state from the template.""" try: state = self._template.async_render().lower() if state in _VALID_STATES: self._state = state in ('true', STATE_ON) else: _LOGGER.error( 'Received invalid switch is_on state: %s. Expected: %s', state, ', '.join(_VALID_STATES)) self._state = None except TemplateError as ex: _LOGGER.error(ex) self._state = None
class WolSwitch(SwitchEntity): """Representation of a wake on lan switch.""" def __init__( self, hass, name, host, mac_address, off_action, broadcast_address, broadcast_port, ): """Initialize the WOL switch.""" self._hass = hass self._name = name self._host = host self._mac_address = mac_address self._broadcast_address = broadcast_address self._broadcast_port = broadcast_port self._off_script = Script(hass, off_action) if off_action else None self._state = False @property def is_on(self): """Return true if switch is on.""" return self._state @property def name(self): """Return the name of the switch.""" return self._name def turn_on(self, **kwargs): """Turn the device on.""" service_kwargs = {} if self._broadcast_address is not None: service_kwargs["ip_address"] = self._broadcast_address if self._broadcast_port is not None: service_kwargs["port"] = self._broadcast_port _LOGGER.info( "Send magic packet to mac %s (broadcast: %s, port: %s)", self._mac_address, self._broadcast_address, self._broadcast_port, ) wakeonlan.send_magic_packet(self._mac_address, **service_kwargs) def turn_off(self, **kwargs): """Turn the device off if an off action is present.""" if self._off_script is not None: self._off_script.run() def update(self): """Check if device is on and update the state.""" if platform.system().lower() == "windows": ping_cmd = [ "ping", "-n", "1", "-w", str(DEFAULT_PING_TIMEOUT * 1000), str(self._host), ] else: ping_cmd = [ "ping", "-c", "1", "-W", str(DEFAULT_PING_TIMEOUT), str(self._host), ] status = sp.call(ping_cmd, stdout=sp.DEVNULL, stderr=sp.DEVNULL) self._state = not bool(status)
class SwitchTemplate(SwitchDevice): """Representation of a Template switch.""" def __init__(self, hass, device_id, friendly_name, state_template, icon_template, on_action, off_action, entity_ids): """Initialize the Template switch.""" self.hass = hass self.entity_id = async_generate_entity_id( ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._template = state_template self._on_script = Script(hass, on_action) self._off_script = Script(hass, off_action) self._state = False self._icon_template = icon_template self._icon = None self._entities = entity_ids @asyncio.coroutine def async_added_to_hass(self): """Register callbacks.""" state = yield from async_get_last_state(self.hass, self.entity_id) if state: self._state = state.state == STATE_ON @callback def template_switch_state_listener(entity, old_state, new_state): """Handle target device state changes.""" self.hass.async_add_job(self.async_update_ha_state(True)) @callback def template_switch_startup(event): """Update template on startup.""" async_track_state_change( self.hass, self._entities, template_switch_state_listener) self.hass.async_add_job(self.async_update_ha_state(True)) self.hass.bus.async_listen_once( EVENT_HOMEASSISTANT_START, template_switch_startup) @property def name(self): """Return the name of the switch.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def should_poll(self): """Return the polling state.""" return False @property def available(self): """If switch is available.""" return self._state is not None @property def icon(self): """Return the icon to use in the frontend, if any.""" return self._icon def turn_on(self, **kwargs): """Fire the on action.""" self._on_script.run() def turn_off(self, **kwargs): """Fire the off action.""" self._off_script.run() @asyncio.coroutine def async_update(self): """Update the state from the template.""" try: state = self._template.async_render().lower() if state in _VALID_STATES: self._state = state in ('true', STATE_ON) else: _LOGGER.error( 'Received invalid switch is_on state: %s. Expected: %s', state, ', '.join(_VALID_STATES)) self._state = None except TemplateError as ex: _LOGGER.error(ex) self._state = None if self._icon_template is not None: try: self._icon = self._icon_template.async_render() except TemplateError as ex: if ex.args and ex.args[0].startswith( "UndefinedError: 'None' has no attribute"): # Common during HA startup - so just a warning _LOGGER.warning('Could not render icon template %s,' ' the state is unknown.', self._name) return self._icon = super().icon _LOGGER.error('Could not render icon template %s: %s', self._name, ex)
class SwitchTemplate(SwitchDevice): """Representation of a Template switch.""" # pylint: disable=too-many-arguments def __init__(self, hass, device_id, friendly_name, state_template, on_action, off_action, entity_ids): """Initialize the Template switch.""" self.hass = hass self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._template = state_template self._on_script = Script(hass, on_action) self._off_script = Script(hass, off_action) self._state = False self.update() def template_switch_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" self.update_ha_state(True) track_state_change(hass, entity_ids, template_switch_state_listener) @property def name(self): """Return the name of the switch.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def should_poll(self): """No polling needed.""" return False @property def available(self): """If switch is available.""" return self._state is not None def turn_on(self, **kwargs): """Fire the on action.""" self._on_script.run() def turn_off(self, **kwargs): """Fire the off action.""" self._off_script.run() def update(self): """Update the state from the template.""" try: state = template.render(self.hass, self._template).lower() if state in _VALID_STATES: self._state = state in ('true', STATE_ON) else: _LOGGER.error( 'Received invalid switch is_on state: %s. Expected: %s', state, ', '.join(_VALID_STATES)) self._state = None except TemplateError as ex: _LOGGER.error(ex) self._state = None
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # Assume that the TV is not muted self._muted = False # Assume that the TV is in Play mode self._playing = True self._volume = 0 self._current_source = None self._current_source_id = None self._state = STATE_UNKNOWN self._source_list = {} self._app_list = {} self._channel = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (STATE_UNKNOWN, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (not conf_sources or app['id'] in conf_sources or any(word in app['title'] for word in conf_sources) or any(word in app['id'] for word in conf_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): if source['id'] == self._current_source_id: self._current_source = source['label'] self._source_list[source['label']] = source elif (not conf_sources or source['label'] in conf_sources or any(source['label'].find(word) != -1 for word in conf_sources)): self._source_list[source['label']] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @property def name(self): """Return the name of the device.""" return self._name @property def state(self): """Return the state of the device.""" return self._state @property def is_volume_muted(self): """Boolean if volume is currently muted.""" return self._muted @property def volume_level(self): """Volume level of the media player (0..1).""" return self._volume / 100.0 @property def source(self): """Return the current input source.""" return self._current_source @property def source_list(self): """List of available input sources.""" return sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ('channelName' in self._channel): return self._channel['channelName'] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]['largeIcon'] if not icon.startswith('http'): icon = self._app_list[self._current_source_id]['icon'] return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: return SUPPORT_WEBOSTV | SUPPORT_TURN_ON return SUPPORT_WEBOSTV def turn_off(self): """Turn off media player.""" from websockets.exceptions import ConnectionClosed self._state = STATE_OFF try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() def volume_up(self): """Volume up the media player.""" self._client.volume_up() def volume_down(self): """Volume down media player.""" self._client.volume_down() def set_volume_level(self, volume): """Set volume level, range 0..1.""" tv_volume = volume * 100 self._client.set_volume(tv_volume) def mute_volume(self, mute): """Send mute command.""" self._muted = mute self._client.set_mute(mute) def media_play_pause(self): """Simulate play pause media player.""" if self._playing: self.media_pause() else: self.media_play() def select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict['id'] if source_dict.get('title'): self._current_source = source_dict['title'] self._client.launch_app(source_dict['id']) elif source_dict.get('label'): self._current_source = source_dict['label'] self._client.set_input(source_dict['id']) def media_play(self): """Send play command.""" self._playing = True self._state = STATE_PLAYING self._client.play() def media_pause(self): """Send media pause command to media player.""" self._playing = False self._state = STATE_PAUSED self._client.pause() def media_next_track(self): """Send next track command.""" self._client.fast_forward() def media_previous_track(self): """Send the previous track command.""" self._client.rewind()
class SwitchTemplate(SwitchDevice): """Representation of a Template switch.""" def __init__(self, hass, device_id, friendly_name, state_template, icon_template, on_action, off_action, entity_ids): """Initialize the Template switch.""" self.hass = hass self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._template = state_template self._on_script = Script(hass, on_action) self._off_script = Script(hass, off_action) self._state = False self._icon_template = icon_template self._icon = None self._entities = entity_ids @asyncio.coroutine def async_added_to_hass(self): """Register callbacks.""" state = yield from async_get_last_state(self.hass, self.entity_id) if state: self._state = state.state == STATE_ON @callback def template_switch_state_listener(entity, old_state, new_state): """Handle target device state changes.""" self.hass.async_add_job(self.async_update_ha_state(True)) @callback def template_switch_startup(event): """Update template on startup.""" async_track_state_change(self.hass, self._entities, template_switch_state_listener) self.hass.async_add_job(self.async_update_ha_state(True)) if self._template: self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, template_switch_startup) @property def name(self): """Return the name of the switch.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def should_poll(self): """Return the polling state.""" return False @property def available(self): """If switch is available.""" return self._state is not None @property def assumed_state(self): """Return true if we do internal state tracking.""" return self._template is None @property def icon(self): """Return the icon to use in the frontend, if any.""" return self._icon def turn_on(self, **kwargs): """Fire the on action.""" self._on_script.run() if not self._template: self._state = True self.schedule_update_ha_state() def turn_off(self, **kwargs): """Fire the off action.""" self._off_script.run() if not self._template: self._state = False self.schedule_update_ha_state() @asyncio.coroutine def async_update(self): """Update the state from the template.""" if self._template is not None: try: state = self._template.async_render().lower() if state in _VALID_STATES: self._state = state in ('true', STATE_ON) else: _LOGGER.error( 'Received invalid switch is_on state: %s.' ' Expected: %s', state, ', '.join(_VALID_STATES)) self._state = None except TemplateError as ex: _LOGGER.error(ex) self._state = None if self._icon_template is not None: try: self._icon = self._icon_template.async_render() except TemplateError as ex: if ex.args and ex.args[0].startswith( "UndefinedError: 'None' has no attribute"): # Common during HA startup - so just a warning _LOGGER.warning( 'Could not render icon template %s,' ' the state is unknown.', self._name) return self._icon = super().icon _LOGGER.error('Could not render icon template %s: %s', self._name, ex)