From 5dabfed3651505d546eceff9ffbdda8675e024bc Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Sat, 1 Apr 2023 22:31:24 +0200 Subject: [PATCH] Migrated `sensor.bme280` to the new `SensorPlugin` interface. Removed the old `backend.sensor.bme280` and the old `gpio.sensor.bme280` plugin. They have now been merged into the new `sensor.bme280` runnable plugin, which extends the `SensorPlugin` API and supports entities. --- platypush/backend/sensor/bme280/__init__.py | 39 ----- platypush/backend/sensor/bme280/manifest.yaml | 13 -- .../plugins/gpio/sensor/bme280/__init__.py | 63 ------- .../plugins/gpio/sensor/bme280/manifest.yaml | 7 - platypush/plugins/sensor/bme280/__init__.py | 155 ++++++++++++++++++ platypush/plugins/sensor/bme280/manifest.yaml | 10 ++ 6 files changed, 165 insertions(+), 122 deletions(-) delete mode 100644 platypush/backend/sensor/bme280/__init__.py delete mode 100644 platypush/backend/sensor/bme280/manifest.yaml delete mode 100644 platypush/plugins/gpio/sensor/bme280/__init__.py delete mode 100644 platypush/plugins/gpio/sensor/bme280/manifest.yaml create mode 100644 platypush/plugins/sensor/bme280/__init__.py create mode 100644 platypush/plugins/sensor/bme280/manifest.yaml diff --git a/platypush/backend/sensor/bme280/__init__.py b/platypush/backend/sensor/bme280/__init__.py deleted file mode 100644 index 3690424f..00000000 --- a/platypush/backend/sensor/bme280/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -from platypush.backend.sensor import SensorBackend - - -class SensorBme280Backend(SensorBackend): - """ - Backend to poll analog sensor values from a `BME280 `_ - environment sensor - - Requires: - - * ``pimoroni-bme280`` (``pip install pimoroni-bme280``) - - Triggers: - - * :class:`platypush.message.event.sensor.SensorDataChangeEvent` if the measurements of a sensor have changed - * :class:`platypush.message.event.sensor.SensorDataAboveThresholdEvent` if the measurements of a sensor have - gone above a configured threshold - * :class:`platypush.message.event.sensor.SensorDataBelowThresholdEvent` if the measurements of a sensor have - gone below a configured threshold - - """ - - def __init__(self, temperature=True, pressure=True, humidity=True, **kwargs): - """ - :param temperature: Enable temperature sensor polling - :param pressure: Enable pressure sensor polling - :param humidity: Enable humidity sensor polling - """ - - enabled_sensors = { - 'temperature': temperature, - 'pressure': pressure, - 'humidity': humidity, - } - - super().__init__(plugin='gpio.sensor.bme280', enabled_sensors=enabled_sensors, **kwargs) - - -# vim:sw=4:ts=4:et: diff --git a/platypush/backend/sensor/bme280/manifest.yaml b/platypush/backend/sensor/bme280/manifest.yaml deleted file mode 100644 index 6b2981ee..00000000 --- a/platypush/backend/sensor/bme280/manifest.yaml +++ /dev/null @@ -1,13 +0,0 @@ -manifest: - events: - platypush.message.event.sensor.SensorDataAboveThresholdEvent: if the measurements - of a sensor havegone above a configured threshold - platypush.message.event.sensor.SensorDataBelowThresholdEvent: if the measurements - of a sensor havegone below a configured threshold - platypush.message.event.sensor.SensorDataChangeEvent: if the measurements of a - sensor have changed - install: - pip: - - pimoroni-bme280 - package: platypush.backend.sensor.bme280 - type: backend diff --git a/platypush/plugins/gpio/sensor/bme280/__init__.py b/platypush/plugins/gpio/sensor/bme280/__init__.py deleted file mode 100644 index 7411ec77..00000000 --- a/platypush/plugins/gpio/sensor/bme280/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -from platypush.plugins import action -from platypush.plugins.gpio.sensor import GpioSensorPlugin - - -class GpioSensorBme280Plugin(GpioSensorPlugin): - """ - Plugin to interact with a `BME280 `_ environment sensor for - temperature, humidity and pressure measurements over I2C interface - - Requires: - - * ``pimoroni-bme280`` (``pip install pimoroni-bme280``) - """ - - def __init__(self, port=1, **kwargs): - """ - :param port: I2C port. 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) - """ - - super().__init__(**kwargs) - self.port = port - self._bus = None - self._device = None - - # noinspection PyPackageRequirements - # noinspection PyUnresolvedReferences - def _get_device(self): - if self._device: - return self._device - - from smbus import SMBus - from bme280 import BME280 - - self._bus = SMBus(self.port) - self._device = BME280(i2c_dev=self._bus) - return self._device - - @action - def get_measurement(self): - """ - :returns: dict. Example: - - .. code-block:: python - - output = { - "temperature": 21.0, # Celsius - "pressure": 101555.08, # Pascals - "humidity": 23.543, # percentage - "altitude": 15.703 # meters - } - - """ - - device = self._get_device() - return { - 'temperature': device.get_temperature(), - 'pressure': device.get_pressure()*100, - 'humidity': device.get_humidity(), - 'altitude': device.get_altitude(), - } - - -# vim:sw=4:ts=4:et: diff --git a/platypush/plugins/gpio/sensor/bme280/manifest.yaml b/platypush/plugins/gpio/sensor/bme280/manifest.yaml deleted file mode 100644 index ad8a2fb6..00000000 --- a/platypush/plugins/gpio/sensor/bme280/manifest.yaml +++ /dev/null @@ -1,7 +0,0 @@ -manifest: - events: {} - install: - pip: - - pimoroni-bme280 - package: platypush.plugins.gpio.sensor.bme280 - type: plugin diff --git a/platypush/plugins/sensor/bme280/__init__.py b/platypush/plugins/sensor/bme280/__init__.py new file mode 100644 index 00000000..724a093e --- /dev/null +++ b/platypush/plugins/sensor/bme280/__init__.py @@ -0,0 +1,155 @@ +from dataclasses import dataclass +from typing import Dict, List, Type +from typing_extensions import override + +from platypush.common.sensors import Numeric +from platypush.entities.devices import Device +from platypush.entities.distance import DistanceSensor +from platypush.entities.humidity import HumiditySensor +from platypush.entities.pressure import PressureSensor +from platypush.entities.sensors import NumericSensor +from platypush.entities.temperature import TemperatureSensor +from platypush.plugins import action +from platypush.plugins.sensor import SensorPlugin + + +@dataclass +class SensorEntityMapping: + """ + Maps the dict-like data returned by the plugin to corresponding sensor + entities. + """ + + name: str + unit: str + entity_type: Type[NumericSensor] + + @property + def id(self): + """ + The standardized external ID for the entity. + """ + return f'bme280:{self.name}' + + +_sensor_entity_mappings = { + mapping.name: mapping + for mapping in [ + SensorEntityMapping( + name='temperature', + unit='°C', + entity_type=TemperatureSensor, + ), + SensorEntityMapping( + name='humidity', + unit='%', + entity_type=HumiditySensor, + ), + SensorEntityMapping( + name='pressure', + unit='Pa', + entity_type=PressureSensor, + ), + SensorEntityMapping( + name='altitude', + unit='m', + entity_type=DistanceSensor, + ), + ] +} + + +# pylint: disable=too-many-ancestors +class SensorBme280Plugin(SensorPlugin): + """ + Plugin to interact with a `BME280 `_ environment sensor for + temperature, humidity and pressure measurements over I2C interface + + Requires: + + * ``pimoroni-bme280`` (``pip install pimoroni-bme280``) + + Triggers: + + * :class:`platypush.message.event.sensor.SensorDataAboveThresholdEvent` + * :class:`platypush.message.event.sensor.SensorDataBelowThresholdEvent` + * :class:`platypush.message.event.sensor.SensorDataChangeEvent` + + """ + + def __init__(self, port: int = 1, **kwargs): + """ + :param port: I2C port. 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) + """ + + super().__init__(**kwargs) + self.port = port + self._bus = None + self._device = None + + def _get_device(self): + from smbus import SMBus + from bme280 import BME280 + + if self._device: + return self._device + + self._bus = SMBus(self.port) + self._device = BME280(i2c_dev=self._bus) + return self._device + + @override + @action + def get_measurement(self, *_, **__): + """ + :returns: dict. Example: + + .. code-block:: python + + output = { + "temperature": 21.0, # Celsius + "pressure": 101555.08, # Pascals + "humidity": 23.543, # percentage + "altitude": 15.703 # meters + } + + """ + + device = self._get_device() + return { + 'temperature': device.get_temperature(), + 'pressure': device.get_pressure() * 100, + 'humidity': device.get_humidity(), + 'altitude': device.get_altitude(), + } + + @override + def transform_entities(self, entities: Dict[str, Numeric]) -> List[Device]: + sensors = [] + for sensor, value in entities.items(): + if value is None: + continue + + mapping = _sensor_entity_mappings[sensor] + sensors.append( + mapping.entity_type( + id=mapping.id, + name=mapping.name, + value=value, + unit=mapping.unit, + ) + ) + + if not sensors: + return [] + + return [ + Device( + id='bme280', + name='BME280 Sensor', + children=sensors, + ) + ] + + +# vim:sw=4:ts=4:et: diff --git a/platypush/plugins/sensor/bme280/manifest.yaml b/platypush/plugins/sensor/bme280/manifest.yaml new file mode 100644 index 00000000..3ea74b94 --- /dev/null +++ b/platypush/plugins/sensor/bme280/manifest.yaml @@ -0,0 +1,10 @@ +manifest: + events: + platypush.message.event.sensor.SensorDataAboveThresholdEvent: + platypush.message.event.sensor.SensorDataBelowThresholdEvent: + platypush.message.event.sensor.SensorDataChangeEvent: + install: + pip: + - pimoroni-bme280 + package: platypush.plugins.sensor.bme280 + type: plugin