-
-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Telnet switch #8913
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
Telnet switch #8913
Changes from 6 commits
b204c72
dd75053
e9c4a3d
47e4be0
0ded0a7
961601f
a393c16
e80fd7d
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,146 @@ | ||
| """ | ||
| Support for switch controlled using a telnet connection. | ||
|
|
||
| For more details about this platform, please refer to the documentation at | ||
| https://home-assistant.io/components/switch.telnet/ | ||
| """ | ||
| import logging | ||
| import telnetlib | ||
| from datetime import timedelta | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA, | ||
| ENTITY_ID_FORMAT) | ||
| from homeassistant.const import ( | ||
| CONF_RESOURCE, CONF_FRIENDLY_NAME, CONF_SWITCHES, CONF_VALUE_TEMPLATE, | ||
| CONF_COMMAND_OFF, CONF_COMMAND_ON, CONF_COMMAND_STATE, CONF_PORT) | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| DEFAULT_PORT = 23 | ||
|
|
||
| SWITCH_SCHEMA = vol.Schema({ | ||
| vol.Required(CONF_RESOURCE): cv.string, | ||
| vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, | ||
| vol.Required(CONF_COMMAND_OFF): cv.string, | ||
| vol.Required(CONF_COMMAND_ON): cv.string, | ||
| vol.Optional(CONF_COMMAND_STATE): cv.string, | ||
| vol.Optional(CONF_FRIENDLY_NAME): cv.string, | ||
|
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. Please use |
||
| vol.Required(CONF_VALUE_TEMPLATE): cv.template, | ||
| }) | ||
|
|
||
| PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||
| vol.Required(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}), | ||
| }) | ||
|
|
||
| SCAN_INTERVAL = timedelta(seconds=10) | ||
|
|
||
|
|
||
| # pylint: disable=unused-argument | ||
| def setup_platform(hass, config, add_devices, discovery_info=None): | ||
| """Find and return switches controlled by shell commands.""" | ||
|
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. Stale docstring. |
||
| devices = config.get(CONF_SWITCHES, {}) | ||
| switches = [] | ||
|
|
||
| for object_id, device_config in devices.items(): | ||
| value_template = device_config.get(CONF_VALUE_TEMPLATE) | ||
|
|
||
| if value_template is not None: | ||
| value_template.hass = hass | ||
|
|
||
| switches.append( | ||
| TelnetSwitch( | ||
| hass, | ||
| object_id, | ||
| device_config.get(CONF_RESOURCE), | ||
| device_config.get(CONF_PORT), | ||
| device_config.get(CONF_FRIENDLY_NAME, object_id), | ||
| device_config.get(CONF_COMMAND_ON), | ||
| device_config.get(CONF_COMMAND_OFF), | ||
| device_config.get(CONF_COMMAND_STATE), | ||
| value_template | ||
| ) | ||
| ) | ||
|
|
||
| if not switches: | ||
| _LOGGER.error("No switches added") | ||
| return False | ||
|
|
||
| add_devices(switches) | ||
|
|
||
|
|
||
| class TelnetSwitch(SwitchDevice): | ||
| """Representation of a switch that can be toggled using telnet commands.""" | ||
|
|
||
| def __init__(self, hass, object_id, resource, port, friendly_name, | ||
| command_on, command_off, command_state, value_template): | ||
| """Initialize the switch.""" | ||
| self._hass = hass | ||
| self.entity_id = ENTITY_ID_FORMAT.format(object_id) | ||
| self._resource = resource | ||
| self._port = port | ||
| self._name = friendly_name | ||
| self._state = False | ||
| self._command_on = command_on | ||
| self._command_off = command_off | ||
| self._command_state = command_state | ||
| self._value_template = value_template | ||
|
|
||
| def _telnet_command(self, command): | ||
| try: | ||
| telnet = telnetlib.Telnet(self._resource, self._port) | ||
| telnet.write(command.encode('ASCII') + b'\r') | ||
| response = telnet.read_until(b'\r', timeout=0.2) | ||
| return response.decode('ASCII').strip() | ||
| except IOError as error: | ||
| _LOGGER.error( | ||
| 'Command "%s" failed with exception: %s', | ||
| command, repr(error)) | ||
| return None | ||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the switch.""" | ||
| return self._name | ||
|
|
||
| @property | ||
| def should_poll(self): | ||
| """Only poll if we have state command.""" | ||
| return self._command_state is not None | ||
|
|
||
| @property | ||
| def is_on(self): | ||
| """Return true if device is on.""" | ||
| return self._state | ||
|
|
||
| @property | ||
| def assumed_state(self): | ||
| """Default ist true if no state command is defined, false otherwise.""" | ||
| return self._command_state is None | ||
|
|
||
| def update(self): | ||
| """Update device state.""" | ||
| response = self._telnet_command(self._command_state) | ||
| if response: | ||
| _LOGGER.info( | ||
|
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. Don't log this. Maybe a debug but not more. |
||
| 'Response for command %s: %s', self._command_state, response) | ||
| rendered = self._value_template \ | ||
| .render_with_possible_json_value(response) | ||
| self._state = rendered == "True" | ||
| else: | ||
| _LOGGER.warning( | ||
| "Empty response for command: %s", self._command_state) | ||
|
|
||
| def turn_on(self, **kwargs): | ||
| """Turn the device on.""" | ||
| self._telnet_command(self._command_on) | ||
| if self.assumed_state: | ||
| self._state = True | ||
|
|
||
| def turn_off(self, **kwargs): | ||
| """Turn the device off.""" | ||
| self._telnet_command(self._command_off) | ||
| if self.assumed_state: | ||
| 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.
Would be nice to keep it ordered.