Advertisement
Guest User

broadlinkpower.py

a guest
Jul 6th, 2018
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.41 KB | None | 0 0
  1.  
  2. """
  3. Support for the Broadlink SP2 and SP3s power measurement sensor.
  4. For more details about this platform, please refer to the documentation at
  5. https://home-assistant.io/components/sensor.broadlinkpower/
  6. """
  7. from datetime import timedelta
  8. import binascii
  9. import logging
  10. import socket
  11.  
  12. import voluptuous as vol
  13.  
  14. from homeassistant.components.sensor import PLATFORM_SCHEMA
  15. from homeassistant.const import (
  16. CONF_HOST, CONF_MAC, CONF_MONITORED_CONDITIONS, CONF_NAME, CONF_TIMEOUT)
  17. from homeassistant.helpers.entity import Entity
  18. from homeassistant.util import Throttle
  19. import homeassistant.helpers.config_validation as cv
  20.  
  21. REQUIREMENTS = ['broadlink==0.6']
  22.  
  23. _LOGGER = logging.getLogger(__name__)
  24.  
  25. CONF_UPDATE_INTERVAL = 'update_interval'
  26. DEVICE_DEFAULT_NAME = 'Broadlink power sensor'
  27. DEFAULT_TIMEOUT = 10
  28.  
  29. SENSOR_TYPES = {
  30. 'energy': ['Energy', 'W']
  31. }
  32.  
  33. PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
  34. vol.Optional(CONF_NAME, default=DEVICE_DEFAULT_NAME): vol.Coerce(str),
  35. vol.Optional(CONF_MONITORED_CONDITIONS, default=[]):
  36. vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
  37. vol.Optional(CONF_UPDATE_INTERVAL, default=timedelta(seconds=300)): (
  38. vol.All(cv.time_period, cv.positive_timedelta)),
  39. vol.Required(CONF_HOST): cv.string,
  40. vol.Required(CONF_MAC): cv.string,
  41. vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int
  42. })
  43.  
  44.  
  45. # pylint: disable=unused-argument
  46. def setup_platform(hass, config, add_devices, discovery_info=None):
  47. """Set up the Broadlink device sensors."""
  48. host = config.get(CONF_HOST)
  49. mac = config.get(CONF_MAC).encode().replace(b':', b'')
  50. mac_addr = binascii.unhexlify(mac)
  51. name = config.get(CONF_NAME)
  52. timeout = config.get(CONF_TIMEOUT)
  53. update_interval = config.get(CONF_UPDATE_INTERVAL)
  54.  
  55. broadlink_data = BroadlinkData(update_interval, host, mac_addr, timeout)
  56.  
  57. dev = []
  58. for variable in config[CONF_MONITORED_CONDITIONS]:
  59. dev.append(BroadlinkSensor(name, broadlink_data, variable))
  60. add_devices(dev, True)
  61.  
  62.  
  63. class BroadlinkSensor(Entity):
  64. """Representation of a Broadlink device sensor."""
  65.  
  66. def __init__(self, name, broadlink_data, sensor_type):
  67. """Initialize the sensor."""
  68. self._name = '{} {}'.format(name, SENSOR_TYPES[sensor_type][0])
  69. self._state = None
  70. self._type = sensor_type
  71. self._broadlink_data = broadlink_data
  72. self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
  73.  
  74. @property
  75. def name(self):
  76. """Return the name of the sensor."""
  77. return self._name
  78.  
  79. @property
  80. def state(self):
  81. """Return the state of the sensor."""
  82. return self._state
  83.  
  84. @property
  85. def unit_of_measurement(self):
  86. """Return the unit this state is expressed in."""
  87. return self._unit_of_measurement
  88.  
  89. def update(self):
  90. """Get the latest data from the sensor."""
  91. self._broadlink_data.update()
  92. if self._broadlink_data.data is None:
  93. return
  94. self._state = self._broadlink_data.data[self._type]
  95.  
  96.  
  97. class BroadlinkData(object):
  98. """Representation of a Broadlink data object."""
  99.  
  100. def __init__(self, interval, ip_addr, mac_addr, timeout):
  101. """Initialize the data object."""
  102. import broadlink
  103. self.data = None
  104. self._device = broadlink.sp2((ip_addr, 80), mac_addr)
  105. self._device.timeout = timeout
  106. self._schema = vol.Schema({
  107. vol.Optional('energy'): vol.Range(min=-0, max=3600)
  108. })
  109. self.update = Throttle(interval)(self._update)
  110. if not self._auth():
  111. _LOGGER.warning("Failed to connect to device")
  112.  
  113. def _update(self, retry=3):
  114. try:
  115. data = self._device.get_energy_raw_p3()
  116. if data is not None:
  117. self.data = self._schema(data)
  118. return
  119. except socket.timeout as error:
  120. if retry < 1:
  121. _LOGGER.error(error)
  122. return
  123. except vol.Invalid:
  124. pass # Continue quietly if device returned malformed data
  125. if retry > 0 and self._auth():
  126. self._update(retry-1)
  127.  
  128. def _auth(self, retry=3):
  129. try:
  130. auth = self._device.auth()
  131. except socket.timeout:
  132. auth = False
  133. if not auth and retry > 0:
  134. return self._auth(retry-1)
  135. return auth
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement