diff --git a/.coveragerc b/.coveragerc index 8ccf59dddc9..a4f040696fa 100644 --- a/.coveragerc +++ b/.coveragerc @@ -633,6 +633,7 @@ omit = homeassistant/components/thingspeak/* homeassistant/components/thinkingcleaner/* homeassistant/components/tibber/* + homeassistant/components/tof/sensor.py homeassistant/components/toon/* homeassistant/components/tplink_lte/* homeassistant/components/tradfri/* diff --git a/homeassistant/components/tof/__init__.py b/homeassistant/components/tof/__init__.py new file mode 100644 index 00000000000..0e72aca724b --- /dev/null +++ b/homeassistant/components/tof/__init__.py @@ -0,0 +1 @@ +"""Platform for Time of Flight sensor VL53L1X from STMicroelectronics.""" diff --git a/homeassistant/components/tof/sensor.py b/homeassistant/components/tof/sensor.py new file mode 100644 index 00000000000..a403db03682 --- /dev/null +++ b/homeassistant/components/tof/sensor.py @@ -0,0 +1,125 @@ +"""Platform for Time of Flight sensor VL53L1X from STMicroelectronics.""" + +import asyncio +import logging +from functools import partial + +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +import homeassistant.helpers.config_validation as cv +from homeassistant.components import rpi_gpio +from homeassistant.const import CONF_NAME +from homeassistant.helpers.entity import Entity + +REQUIREMENTS = ['VL53L1X2==0.1.5'] + +DEPENDENCIES = ['rpi_gpio'] + +_LOGGER = logging.getLogger(__name__) + +LENGTH_MILLIMETERS = 'mm' + +CONF_I2C_ADDRESS = 'i2c_address' +CONF_I2C_BUS = 'i2c_bus' +CONF_XSHUT = 'xshut' + +DEFAULT_NAME = 'VL53L1X' +DEFAULT_I2C_ADDRESS = 0x29 +DEFAULT_I2C_BUS = 1 +DEFAULT_XSHUT = 16 +DEFAULT_RANGE = 2 + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, + default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_I2C_ADDRESS, + default=DEFAULT_I2C_ADDRESS): vol.Coerce(int), + vol.Optional(CONF_I2C_BUS, + default=DEFAULT_I2C_BUS): vol.Coerce(int), + vol.Optional(CONF_XSHUT, + default=DEFAULT_XSHUT): cv.positive_int, +}) + + +def init_tof_0(xshut, sensor): + """XSHUT port LOW resets the device.""" + sensor.open() + rpi_gpio.setup_output(xshut) + rpi_gpio.write_output(xshut, 0) + + +def init_tof_1(xshut): + """XSHUT port HIGH enables the device.""" + rpi_gpio.setup_output(xshut) + rpi_gpio.write_output(xshut, 1) + + +async def async_setup_platform(hass, + config, + async_add_entities, + discovery_info=None): + """Reset and initialize the VL53L1X ToF Sensor from STMicroelectronics.""" + from VL53L1X2 import VL53L1X # pylint: disable=import-error + + name = config.get(CONF_NAME) + bus_number = config.get(CONF_I2C_BUS) + i2c_address = config.get(CONF_I2C_ADDRESS) + unit = LENGTH_MILLIMETERS + xshut = config.get(CONF_XSHUT) + + sensor = await hass.async_add_executor_job( + partial(VL53L1X, bus_number) + ) + await hass.async_add_executor_job( + init_tof_0, xshut, sensor + ) + await asyncio.sleep(0.01) + await hass.async_add_executor_job( + init_tof_1, xshut + ) + await asyncio.sleep(0.01) + + dev = [VL53L1XSensor(sensor, name, unit, i2c_address)] + + async_add_entities(dev, True) + + +class VL53L1XSensor(Entity): + """Implementation of VL53L1X sensor.""" + + def __init__(self, vl53l1x_sensor, name, unit, i2c_address): + """Initialize the sensor.""" + self._name = name + self._unit_of_measurement = unit + self.vl53l1x_sensor = vl53l1x_sensor + self.i2c_address = i2c_address + self._state = None + self.init = True + + @property + def name(self) -> str: + """Return the name of the sensor.""" + return self._name + + @property + def state(self) -> int: + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self) -> str: + """Return the unit of measurement.""" + return self._unit_of_measurement + + def update(self): + """Get the latest measurement and update state.""" + if self.init: + self.vl53l1x_sensor.add_sensor( + self.i2c_address, self.i2c_address) + self.init = False + self.vl53l1x_sensor.start_ranging( + self.i2c_address, DEFAULT_RANGE) + self.vl53l1x_sensor.update(self.i2c_address) + self.vl53l1x_sensor.stop_ranging(self.i2c_address) + self._state = self.vl53l1x_sensor.distance diff --git a/requirements_all.txt b/requirements_all.txt index 84083ba7e9a..21fd7de5fb4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -81,6 +81,9 @@ TravisPy==0.3.5 # homeassistant.components.notify.twitter TwitterAPI==2.5.9 +# homeassistant.components.tof.sensor +# VL53L1X2==0.1.5 + # homeassistant.components.sensor.waze_travel_time WazeRouteCalculator==0.9 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 7db76b1361b..25f7fbfc419 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -24,6 +24,7 @@ COMMENT_REQUIREMENTS = ( 'i2csense', 'opencv-python', 'py_noaa', + 'VL53L1X2', 'pybluez', 'pycups', 'PySwitchbot',