Advertisement
Paxy

Untitled

Dec 16th, 2016
527
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.27 KB | None | 0 0
  1. """
  2. Support for Broadlink RM devices.
  3.  
  4. For more details about this platform, please refer to the documentation at
  5. https://home-assistant.io/components/switch.broadlink/
  6. """
  7. from datetime import timedelta
  8. from base64 import b64encode, b64decode
  9. import asyncio
  10. import binascii
  11. import logging
  12. import socket
  13. import voluptuous as vol
  14.  
  15. import homeassistant.loader as loader
  16. from homeassistant.util.dt import utcnow
  17. from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
  18. from homeassistant.const import (CONF_FRIENDLY_NAME, CONF_SWITCHES,
  19.                                  CONF_COMMAND_OFF, CONF_COMMAND_ON,
  20.                                  CONF_TIMEOUT, CONF_HOST, CONF_MAC, CONF_TYPE)
  21. import homeassistant.helpers.config_validation as cv
  22.  
  23. REQUIREMENTS = ['broadlink==0.2']
  24.  
  25. _LOGGER = logging.getLogger(__name__)
  26.  
  27. DOMAIN = "broadlink"
  28. DEFAULT_NAME = 'Broadlink switch'
  29. DEFAULT_TIMEOUT = 10
  30. SERVICE_LEARN = "learn_command"
  31. DEFAULT_TYPE = "RM2"
  32.  
  33. SWITCH_SCHEMA = vol.Schema({
  34.     vol.Optional(CONF_COMMAND_OFF, default=None): cv.string,
  35.     vol.Optional(CONF_COMMAND_ON, default=None): cv.string,
  36.     vol.Optional(CONF_FRIENDLY_NAME, default=DEFAULT_NAME): cv.string,
  37. })
  38.  
  39. PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
  40.     vol.Optional(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}),
  41.     vol.Required(CONF_HOST): cv.string,
  42.     vol.Required(CONF_MAC): cv.string,
  43.     vol.Required(CONF_TYPE, default=DEFAULT_TYPE): cv.string,
  44.     vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int
  45. })
  46.  
  47.  
  48. def setup_platform(hass, config, add_devices, discovery_info=None):
  49.     """Setup Broadlink switches."""
  50.     import broadlink
  51.     devices = config.get(CONF_SWITCHES, {})
  52.     switches = []
  53.     ip_addr = config.get(CONF_HOST)
  54.     mac_addr = binascii.unhexlify(
  55.         config.get(CONF_MAC).encode().replace(b':', b''))
  56.     if (config.get(CONF_TYPE) == 'MP') or (config.get(CONF_TYPE) == 'SP'):
  57.         broadlink_device = broadlink.sp2((ip_addr, 80), mac_addr)
  58.     else:
  59.         broadlink_device = broadlink.rm((ip_addr, 80), mac_addr)
  60.     broadlink_device.timeout = config.get(CONF_TIMEOUT)
  61.     try:
  62.         broadlink_device.auth()
  63.     except socket.timeout:
  64.         _LOGGER.error("Failed to connect to device.")
  65.  
  66.     persistent_notification = loader.get_component('persistent_notification')
  67.  
  68.     @asyncio.coroutine
  69.     def _learn_command(call):
  70.         try:
  71.             yield from hass.loop.run_in_executor(None, broadlink_device.auth)
  72.         except socket.timeout:
  73.             _LOGGER.error("Failed to connect to device.")
  74.             return
  75.         yield from hass.loop.run_in_executor(None,
  76.                                              broadlink_device.enter_learning)
  77.  
  78.         _LOGGER.info("Press the key you want HASS to learn")
  79.         start_time = utcnow()
  80.         while (utcnow() - start_time) < timedelta(seconds=20):
  81.             packet = yield from hass.loop.run_in_executor(None,
  82.                                                           broadlink_device.
  83.                                                           check_data)
  84.             if packet:
  85.                 log_msg = 'Recieved packet is: {}'.\
  86.                           format(b64encode(packet).decode('utf8'))
  87.                 _LOGGER.info(log_msg)
  88.                 persistent_notification.async_create(hass, log_msg,
  89.                                                      title='Broadlink switch')
  90.                 return
  91.             yield from asyncio.sleep(1, loop=hass.loop)
  92.         _LOGGER.error('Did not received any signal.')
  93.         persistent_notification.async_create(hass,
  94.                                              "Did not received any signal",
  95.                                              title='Broadlink switch')
  96.     hass.services.register(DOMAIN, SERVICE_LEARN, _learn_command)
  97.  
  98.     for object_id, device_config in devices.items():
  99.         switches.append(
  100.             BroadlinkRM2Switch(
  101.                 device_config.get(CONF_FRIENDLY_NAME, object_id),
  102.                 device_config.get(CONF_COMMAND_ON),
  103.                 device_config.get(CONF_COMMAND_OFF),
  104.                 broadlink_device
  105.             )
  106.         )
  107.  
  108.     add_devices(switches)
  109.  
  110.  
  111. class BroadlinkRM2Switch(SwitchDevice):
  112.     """Representation of an Broadlink switch."""
  113.  
  114.     def __init__(self, friendly_name, command_on, command_off, device):
  115.         """Initialize the switch."""
  116.         self._name = friendly_name
  117.         self._state = False
  118.         self._command_on = b64decode(command_on) if command_on else None
  119.         self._command_off = b64decode(command_off) if command_off else None
  120.         self._device = device
  121.  
  122.     @property
  123.     def name(self):
  124.         """Return the name of the switch."""
  125.         return self._name
  126.  
  127.     @property
  128.     def assumed_state(self):
  129.         """Return true if unable to access real state of entity."""
  130.         if self._device.type=="RM2":
  131.             return True
  132.         else:
  133.             return self._check_power()
  134.  
  135.     @property
  136.     def is_on(self):
  137.         """Return true if device is on."""
  138.         return self._state
  139.  
  140.     def turn_on(self, **kwargs):
  141.         """Turn the device on."""
  142.         if self._device.type=="RM2":
  143.             self._sendpacket(self._command_on)
  144.         else:
  145.             self._set_power(1)    
  146.         self._state = True
  147.        
  148.     def turn_off(self, **kwargs):
  149.         """Turn the device off."""
  150.         if self._device.type=="RM2":
  151.             self._sendpacket(self._command_on)
  152.         else:
  153.             self._set_power(0)    
  154.         self._state = False
  155.  
  156.     def _sendpacket(self, packet, retry=2):
  157.         """Send packet to device."""
  158.         if packet is None:
  159.             _LOGGER.debug("Empty packet.")
  160.             return True
  161.         try:
  162.             self._device.send_data(packet)
  163.         except socket.timeout as error:
  164.             if retry < 1:
  165.                 _LOGGER.error(error)
  166.                 return False
  167.             try:
  168.                 self._device.auth()
  169.             except socket.timeout:
  170.                 pass
  171.             return self._sendpacket(packet, max(0, retry-1))
  172.         return True
  173.  
  174.     def _check_power(self):
  175.         """Check power"""
  176.         return self._device.check_power()
  177.  
  178.     def _set_power(self,state):
  179.         """Set power"""
  180.         return self._device.set_power(state)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement