| # Copyright 2019 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Drivers for shared functionality provided by the Environment Bonnet.""" |
| |
| import os |
| from luma.core.interface.serial import noop, spi |
| from luma.oled.device import ssd1306 |
| |
| |
| def _get_path(sysfs_name): |
| search_path = '/sys/bus/iio/devices/' |
| try: |
| for fname in os.listdir(search_path): |
| with open(search_path + fname + '/name', 'r') as f: |
| if sysfs_name in f.read(): |
| return search_path + fname |
| return '' |
| except FileNotFoundError: |
| return '' |
| |
| |
| def _read_sysfs(path, retries=2): |
| try: |
| with open(path, 'r') as f: |
| # Allow multiple attempts in case sensor times out. |
| for _ in range(retries): |
| try: |
| data = f.read() |
| if data: |
| return float(data) |
| except: |
| pass |
| return None |
| except FileNotFoundError: |
| return None |
| |
| class EnviroBoard(): |
| def __init__(self): |
| # Obtain the full sysfs path of the IIO devices. |
| self._hdc2010 = _get_path('hdc20x0') |
| self._bmp280 = _get_path('bmp280') |
| self._opt3002 = _get_path('opt3001') |
| self._tla2021 = _get_path('ads1015') |
| # Create SSD1306 OLED instance, with SPI as the interface. |
| self._display = ssd1306(serial_interface=spi(), |
| gpio=noop(), height=32, rotate=2) |
| |
| @property |
| def temperature(self): |
| temperature = _read_sysfs(self._hdc2010 + '/in_temp_input') |
| if temperature is not None: |
| return temperature |
| temperature = _read_sysfs(self._bmp280 + '/in_temp_input') |
| # BMP280 reports as mC. |
| if temperature is not None: |
| return temperature / 1000.0 |
| return None |
| |
| @property |
| def humidity(self): |
| return _read_sysfs(self._hdc2010 + '/in_humidityrelative_input') |
| |
| @property |
| def ambient_light(self): |
| return _read_sysfs(self._opt3002 + '/in_illuminance_input') |
| |
| @property |
| def pressure(self): |
| return _read_sysfs(self._bmp280 + '/in_pressure_input') |
| |
| @property |
| def grove_analog(self): |
| return _read_sysfs(self._tla2021 + '/in_voltage0_raw') |
| |
| @property |
| def display(self): |
| return self._display |