From f705ac6b43af601af41c32fb11b6da0859ed70cb Mon Sep 17 00:00:00 2001 From: Jose Motta Lopes Date: Fri, 8 Mar 2019 04:21:22 -0300 Subject: [PATCH] Add Time of Flight Sensor using VL53L1X (#21230) * Add Time of Flight Sensor using VL53L1X * Fix issues found by bot * Fix issues from bot * Remove extra logs * Keep removing logs dependencies not used * Remove log from update * Add logger info to async_update * Fix over-indented line * Fix pylint error * Remove logger reporting successful operation * Update requirements * Update requirements_all.txt * Update requirements_test_all.txt * Used isort to keep imports and added STMicroelectronics to docstring * Replace time.sleep by asyncio.sleep * Add requirements to COMMENT_REQUIREMENTS and fix typo * Using async_add_executor_job to schedule the call in the pool * Fix typo * Optimize async_update * Updated requirements files * Group and schedule calls that should be run sequentially * Fix lint errors * Revision showing development history * Cleaning and typos * Cleaning and typos * Fix wrong-import-order * Fix gen_requirements_all * Schedule rpi_gpio I/O on the executor thread pool * Fix partial parameters * Fix bot error - add blank line * Fix lint error * Remove dependencies from requirements * Review initial commits * Move all device I/O to async_update * Update requirements_all.txt * Revised header with no url to the docs * Use async_added_to_hass to add and initialize the sensor * Add docstring to init() * Move sensor.open() to async_setup_platform * Remove logging and async * Fix typo * Move sensor.open to safe initialization * Fix typo * Fix typo * Add the new tof module to .coveragerc * Move the sensor platform under a tof package * Update .coveragerc and requirements_all for tof package --- .coveragerc | 1 + homeassistant/components/tof/__init__.py | 1 + homeassistant/components/tof/sensor.py | 125 +++++++++++++++++++++++ requirements_all.txt | 3 + script/gen_requirements_all.py | 1 + 5 files changed, 131 insertions(+) create mode 100644 homeassistant/components/tof/__init__.py create mode 100644 homeassistant/components/tof/sensor.py 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',