sensor.mcp3008#

Description#

Plugin to read analog sensor values from an MCP3008 chipset. The MCP3008 chipset is a circuit that allows you to read measurements from multiple analog sources (e.g. sensors) and multiplex them to a digital device like a Raspberry Pi or a regular laptop. See https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008 for more info.

The MCP3008 can be connected in two modes:

  • Hardware SPI mode: advised if you have enough GPIO pins available

    (and slightly faster)

  • Software SPI mode: useful if you don’t have all the required GPIO

    PINs for hardware SPI available. Slightly slower, as the conversion is done via software, but still relatively performant.

See https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008#wiring for info

Configuration#

sensor.mcp3008:
  # [Optional]
  # (software SPI mode) CLK GPIO PIN
  # CLK:

  # [Optional]
  # (software SPI mode) MISO GPIO PIN
  # MISO:

  # [Optional]
  # (software SPI mode) MOSI GPIO PIN
  # MOSI:

  # [Optional]
  # (software SPI mode) CS GPIO PIN
  # CS:

  # [Optional]
  # (hardware SPI mode) SPI port
  # spi_port:

  # [Optional]
  # (hardware SPI mode) SPI device name
  # spi_device:

  # [Optional]
  # name-value mapping between MCP3008 output PINs and sensor names. This mapping will be used
  # when you get values through `SensorMcp3008Plugin.get_measurement() <https://docs.platypush.tech/platypush/plugins/sensor.mcp3008.html#platypush.plugins.sensor.mcp3008.SensorMcp3008Plugin.get_measurement()>`_. Example::
  #
  #     channels = {
  #         "0": {
  #             "name": "temperature",
  #             "conv_function": 'round(x*100.0, 2)'  # T = Vout / (10 [mV/C])
  #         },
  #         "1": {
  #             "name": "light",  # ALS-PT9
  #             "conv_function": 'round(x*1000.0, 6)'  # ALS-PT9 has a 10 kOhm resistor
  #         }
  #     }
  #
  # Note that you can also pass a conversion function as
  # ``conv_function`` that will convert the output voltage to whichever
  # human-readable value you wish.  In the case above I connected a
  # simple temperature sensor to the channel 0 and a simple ALS-PT9
  # light sensor to the channel 1, and passed the appropriate conversion
  # functions to convert from voltage to, respectively, temperature in
  # Celsius degrees and light intensity in lumen. Note that we reference
  # the current voltage as ``x`` in ``conv_function``.
  # channels:

  # [Optional]
  # Input voltage provided to the circuit (default: 3.3V, Raspberry Pi default power source)
  # Vdd: 3.3

  # [Optional]
  # A number, numeric pair or mapping of ``str`` to
  # number/numeric pair representing the thresholds for the sensor.
  #
  # Examples:
  #
  #     .. code-block:: yaml
  #
  #         # Any value below 25 from any sensor will trigger a
  #         # SensorDataBelowThresholdEvent, if the previous value was
  #         # equal or above, and any value above 25 will trigger a
  #         # SensorDataAboveThresholdEvent, if the previous value was
  #         # equal or below
  #         thresholds: 25.0
  #
  #         # Same as above, but the threshold is only applied to
  #         # ``temperature`` readings
  #         thresholds:
  #             temperature: 25.0
  #
  #         # Any value below 20 from any sensor will trigger a
  #         # SensorDataBelowThresholdEvent, if the previous value was
  #         # equal or above, and any value above 25 will trigger a
  #         # SensorDataAboveThresholdEvent, if the previous value was
  #         # equal or below (hysteresis configuration with double
  #         # threshold)
  #         thresholds:
  #             - 20.0
  #             - 25.0
  #
  #         # Same as above, but the threshold is only applied to
  #         # ``temperature`` readings
  #         thresholds:
  #             temperature:
  #                 - 20.0
  #                 - 25.0
  # thresholds:   # type=Union[float, int, Tuple[Union[float, int], Union[float, int]], Mapping[str, Union[float, int, Tuple[Union[float, int], Union[float, int]]]], NoneType]

  # [Optional]
  # If set, then the sensor change events will be
  # triggered only if the difference between the new value and the
  # previous value is higher than the specified tolerance. For example,
  # if the sensor data is mapped to a dictionary::
  #
  #     {
  #         "temperature": 0.01,  # Tolerance on the 2nd decimal digit
  #         "humidity": 0.1       # Tolerance on the 1st decimal digit
  #     }
  #
  # Or, if it's a raw scalar number::
  #
  #     0.1  # Tolerance on the 1st decimal digit
  #
  # Or, if it's a list of values::
  #
  #     [
  #         0.01,   # Tolerance on the 2nd decimal digit for the first value
  #         0.1     # Tolerance on the 1st decimal digit for the second value
  #     ]
  # tolerance: 0  # type=Union[float, int, Mapping[str, Union[float, int]], Iterable[Union[float, int]]]

  # [Optional]
  # If `SensorPlugin.get_measurement <https://docs.platypush.tech/platypush/plugins/sensor.html#platypush.plugins.sensor.SensorPlugin.get_measurement>`_ returns a key-value
  # mapping, and ``enabled_sensors`` is set, then only the reported
  # sensor keys will be returned.
  # enabled_sensors:   # type=Optional[Iterable[str]]

  # [Optional]
  # How often the `RunnablePlugin.loop <https://docs.platypush.tech/platypush/plugins/.html#platypush.plugins.RunnablePlugin.loop>`_ function should be
  # executed (default: 15 seconds). *NOTE*: For back-compatibility
  # reasons, the `poll_seconds` argument is also supported, but it's
  # deprecated.
  # poll_interval: 15  # type=Optional[float]

  # [Optional]
  # How long we should wait for any running
  # threads/processes to stop before exiting (default: 5 seconds).
  # stop_timeout: 5  # type=Optional[float]

  # [Optional]
  # If set to True then the plugin will not monitor
  # for new events. This is useful if you want to run a plugin in
  # stateless mode and only leverage its actions, without triggering any
  # events. Defaults to False.
  # disable_monitor: False  # type=bool

Dependencies#

pip

pip install adafruit-mcp3008

Triggered events#

Actions#

Module reference#

class platypush.plugins.sensor.mcp3008.MCP3008Mode(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Bases: Enum

MPC3008 mode enum (hardware or software).

class platypush.plugins.sensor.mcp3008.SensorMcp3008Plugin(*_, **__)[source]#

Bases: SensorPlugin

Plugin to read analog sensor values from an MCP3008 chipset. The MCP3008 chipset is a circuit that allows you to read measurements from multiple analog sources (e.g. sensors) and multiplex them to a digital device like a Raspberry Pi or a regular laptop. See https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008 for more info.

__init__(CLK=None, MISO=None, MOSI=None, CS=None, spi_port=None, spi_device=None, channels=None, Vdd=3.3, **kwargs)[source]#

The MCP3008 can be connected in two modes:

  • Hardware SPI mode: advised if you have enough GPIO pins available

    (and slightly faster)

  • Software SPI mode: useful if you don’t have all the required GPIO

    PINs for hardware SPI available. Slightly slower, as the conversion is done via software, but still relatively performant.

See https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008#wiring for info

Parameters:
  • CLK (int) – (software SPI mode) CLK GPIO PIN

  • MISO (int) – (software SPI mode) MISO GPIO PIN

  • MOSI (int) – (software SPI mode) MOSI GPIO PIN

  • CS (int) – (software SPI mode) CS GPIO PIN

  • spi_port (int) – (hardware SPI mode) SPI port

  • spi_device (str) – (hardware SPI mode) SPI device name

  • channels (dict) –

    name-value mapping between MCP3008 output PINs and sensor names. This mapping will be used when you get values through get_measurement(). Example:

    channels = {
        "0": {
            "name": "temperature",
            "conv_function": 'round(x*100.0, 2)'  # T = Vout / (10 [mV/C])
        },
        "1": {
            "name": "light",  # ALS-PT9
            "conv_function": 'round(x*1000.0, 6)'  # ALS-PT9 has a 10 kOhm resistor
        }
    }
    

    Note that you can also pass a conversion function as conv_function that will convert the output voltage to whichever human-readable value you wish. In the case above I connected a simple temperature sensor to the channel 0 and a simple ALS-PT9 light sensor to the channel 1, and passed the appropriate conversion functions to convert from voltage to, respectively, temperature in Celsius degrees and light intensity in lumen. Note that we reference the current voltage as x in conv_function.

  • Vdd (float) – Input voltage provided to the circuit (default: 3.3V, Raspberry Pi default power source)

get_data(*args, **kwargs)#

(Deprecated) alias for get_measurement()

get_measurement()[source]#

Returns a measurement from the sensors connected to the MCP3008 device. If channels were passed to the configuration, the appropriate sensor names will be used and the voltage will be converted through the appropriate conversion function. Example:

output = {
    "temperature": 21.0,  # Celsius
    "humidity": 45.1    # %
}

Otherwise, the output dictionary will contain the channel numbers as key and the row voltage (between 0 and 255) will be returned. Example:

output = {
    "0": 145,
    "1": 130
}
main()#

Implementation of the main loop of the plugin.

publish_entities(entities: float | int | Mapping[str, float | int] | Iterable[float | int], *args, **kwargs) Collection[Entity]#

Publishes a list of entities. The downstream consumers include:

It also accepts an optional callback that will be called when each of the entities in the set is flushed to the database.

You usually don’t need to override this class (but you may want to extend transform_entities() instead if your extension doesn’t natively handle Entity objects).

start()#

Start the plugin.

status(*_, **__) float | int | Mapping[str, float | int] | Iterable[float | int] | None#

Returns the latest read values and publishes the platypush.message.event.entities.EntityUpdateEvent events if required.

stop()#

Stop the plugin.

transform_entities(entities: Dict[str, float | int]) List[Device][source]#

This method takes a list of entities in any (plugin-specific) format and converts them into a standardized collection of Entity objects. Since this method is called by publish_entities() before entity updates are published, you may usually want to extend it to pre-process the entities managed by your extension into the standard format before they are stored and published to all the consumers.

wait_stop(timeout=None)#

Wait until a stop event is received.