diff --git a/homeassistant/components/switch/broadlink.py b/homeassistant/components/switch/broadlink.py index ee71de3a22e..786ac5f06f5 100644 --- a/homeassistant/components/switch/broadlink.py +++ b/homeassistant/components/switch/broadlink.py @@ -17,7 +17,8 @@ from homeassistant.util.dt import utcnow from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import (CONF_FRIENDLY_NAME, CONF_SWITCHES, CONF_COMMAND_OFF, CONF_COMMAND_ON, - CONF_TIMEOUT, CONF_HOST, CONF_MAC) + CONF_TIMEOUT, CONF_HOST, CONF_MAC, + CONF_TYPE) import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['broadlink==0.2'] @@ -29,6 +30,8 @@ DEFAULT_NAME = 'Broadlink switch' DEFAULT_TIMEOUT = 10 SERVICE_LEARN = "learn_command" +SENSOR_TYPES = ["rm", "sp1", "sp2"] + SWITCH_SCHEMA = vol.Schema({ vol.Optional(CONF_COMMAND_OFF, default=None): cv.string, vol.Optional(CONF_COMMAND_ON, default=None): cv.string, @@ -39,6 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}), vol.Required(CONF_HOST): cv.string, vol.Required(CONF_MAC): cv.string, + vol.Optional(CONF_TYPE, default=SENSOR_TYPES[0]): vol.In(SENSOR_TYPES), vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int }) @@ -51,7 +55,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): ip_addr = config.get(CONF_HOST) mac_addr = binascii.unhexlify( config.get(CONF_MAC).encode().replace(b':', b'')) - broadlink_device = broadlink.rm((ip_addr, 80), mac_addr) + sensor_type = config.get(CONF_TYPE) + + if sensor_type == "rm": + broadlink_device = broadlink.rm((ip_addr, 80), mac_addr) + switch = BroadlinkRMSwitch + elif sensor_type == "sp1": + broadlink_device = broadlink.sp1((ip_addr, 80), mac_addr) + switch = BroadlinkSP1Switch + elif sensor_type == "sp2": + broadlink_device = broadlink.sp2((ip_addr, 80), mac_addr) + switch = BroadlinkSP2Switch + broadlink_device.timeout = config.get(CONF_TIMEOUT) try: broadlink_device.auth() @@ -92,7 +107,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for object_id, device_config in devices.items(): switches.append( - BroadlinkRM2Switch( + switch( device_config.get(CONF_FRIENDLY_NAME, object_id), device_config.get(CONF_COMMAND_ON), device_config.get(CONF_COMMAND_OFF), @@ -103,7 +118,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices(switches) -class BroadlinkRM2Switch(SwitchDevice): +class BroadlinkRMSwitch(SwitchDevice): """Representation of an Broadlink switch.""" def __init__(self, friendly_name, command_on, command_off, device): @@ -124,6 +139,11 @@ class BroadlinkRM2Switch(SwitchDevice): """Return true if unable to access real state of entity.""" return True + @property + def should_poll(self): + """No polling needed.""" + return False + @property def is_on(self): """Return true if device is on.""" @@ -156,3 +176,66 @@ class BroadlinkRM2Switch(SwitchDevice): pass return self._sendpacket(packet, max(0, retry-1)) return True + + +class BroadlinkSP1Switch(BroadlinkRMSwitch): + """Representation of an Broadlink switch.""" + + def __init__(self, friendly_name, command_on, command_off, device): + """Initialize the switch.""" + super().__init__(friendly_name, command_on, command_off, device) + self._command_on = 1 + self._command_off = 0 + + def _sendpacket(self, packet, retry=2): + """Send packet to device.""" + try: + self._device.set_power(packet) + except socket.timeout as error: + if retry < 1: + _LOGGER.error(error) + return False + try: + self._device.auth() + except socket.timeout: + pass + return self._sendpacket(packet, max(0, retry-1)) + return True + + +class BroadlinkSP2Switch(BroadlinkSP1Switch): + """Representation of an Broadlink switch.""" + + def __init__(self, friendly_name, command_on, command_off, device): + """Initialize the switch.""" + super().__init__(friendly_name, command_on, command_off, device) + + @property + def assumed_state(self): + """Return true if unable to access real state of entity.""" + return False + + @property + def should_poll(self): + """Polling needed.""" + return True + + def update(self): + """Synchronize state with switch.""" + self._update() + + def _update(self, retry=2): + try: + state = self._device.check_power() + except socket.timeout as error: + if retry < 1: + _LOGGER.error(error) + return + try: + self._device.auth() + except socket.timeout: + pass + return self._update(max(0, retry-1)) + if state is None and retry > 0: + return self._update(max(0, retry-1)) + self._state = state