mqttwrapper


Namemqttwrapper JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/davea/mqttwrapper
SummaryMQTT utility scripts made easy
upload_time2024-03-02 15:04:21
maintainer
docs_urlNone
authorDave Arter
requires_python
licenseMIT
keywords mqtt
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            mqttwrapper
===========

A little glue package to make it simple to quickly put together scripts that
bridge MQTT and other libraries. See examples below.

Installation
------------

Install from PyPI::

  $ pip install mqttwrapper

By default ``paho-mqtt`` will be used as the MQTT library, but you can use
``hbmqtt`` if you wish, though support for this is deprecated and will be
removed in the future. To install, use::

  $ pip install mqttwrapper[hbmqtt]

Usage
-----

``mqttwrapper.run_script`` handles the setup/maintenance of the MQTT connection
and subscriptions to topics, and calls a callback function when messages are
received. It can run in blocking mode where it will take care of the MQTT
client handling or in non blocking mode where a new thread takes care this
leaving your main thread free for other things.

The simplest script looks something like this::

  from mqttwrapper import run_script

  def callback(topic, payload):
      print("Received payload {} on topic {}".format(payload, topic))

  def main():
      run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"])

or in non blocking mode::

  def main():
      run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"], blocking=False)
      while True:
          echo "Alive and kicking"
          time.sleep(1)

Any extra keyword arguments passed to ``run_script`` are passed back to the
callback function when it's called::

  from mqttwrapper import run_script

  def callback(topic, payload, context, foo):
      assert context == "hello"
      assert foo == "bar"
      print("Received payload {} on topic {}".format(payload, topic))

  def main():
      run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"], context="hello", foo="bar")


If you don't need any context passed to your callback, just the topic and
payload of messages, you can run in 'importless' mode by creating a `callback`
module which has a `callback` function defined, then execute the
`mqttwrapper.run` module::

  $ cat callback.py
  def callback(topic, payload):
      print(topic, payload)
  
  $ python -m mqttwrapper.run

Retained messages
-----------------

You can ignore MQTT retained messages by passing ``ignore_retained=True`` when
calling ``run_script``. NB this is currently not supported by the hbmqtt
backend.

Publishing messages from the callback
-------------------------------------

Sometimes your callback function might want to publish its own MQTT messages,
perhaps in reply to or an acknowledgement of a received message. This is
possible by returning an iterable of ``(topic, payload)`` tuples from the callback,
e.g.::

    def callback(topic, payload):
      print("Received payload {} on topic {}".format(payload, topic))
      return [
        ("{}/ack".format(topic), payload)
      ]


``mqttwrapper`` will take care of publishing these messages to the broker.

These tuples can optionally take the form ``(topic, payload, True)`` if you want
the published message to be marked as retained.

Configuration
-------------

``broker`` and ``topics`` can be omitted from the ``run_script`` call and
environment variables used instead:

- ``MQTT_BROKER``: MQTT broker to connect to, e.g. ``mqtt://127.0.0.1/``
- ``MQTT_TOPICS``: Comma-separated list of topics to subscribe to, e.g. ``my/topic1,my/topic2``

asyncio/hbmqtt
--------------

NB This feature is deprecated and will be removed in the future.

The asyncio-powered ``hbmqtt`` MQTT library can be used instead, if you like::

  from mqttwrapper.hbmqtt_backend import run_script

  async def callback(topic, payload):
      print("Received payload {} on topic {}".format(payload, topic))


Note that your callback must be an awaitable in this case.

Your callback may require context arguments which themselves are async objects
or awaitables which poses a challenge: how to set these up outside of an asyncio
event loop before calling ``run_script``? In this case, you can pass a
``context_callback`` awaitable as a kwarg to ``run_script``. This is run at the
start of the MQTT loop, and should return a dict which will be merged into the
kwargs which are passed to your callback. For example::

  from mqttwrapper.hbmqtt_backend import run_script

  async def setup_db():
    return {
      "query_db": query_db
    }

  async def query_db(value):
    # pretend this is some slow DB query, for example.
    await asyncio.sleep(3)
    return value * 2

  async def callback(topic, payload, query_db):
      db_result = await query_db(int(payload))
      print("Received payload {} on topic {}, db result: {}".format(payload, topic, db_result))

  def main():
      run_script(callback, context_callback=setup_db)


NB hbmqtt's reconnection handling does not resubscribe to topics upon
reconnection, and ``mqttwrapper`` does not yet work around this.

Examples
--------

- rxv2mqtt_
- tradfri-mqtt_ (uses asyncio)

.. _rxv2mqtt: https://github.com/davea/rxv2mqtt/blob/master/main.py
.. _tradfri-mqtt: https://github.com/davea/tradfri-mqtt/blob/master/main.py



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/davea/mqttwrapper",
    "name": "mqttwrapper",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "mqtt",
    "author": "Dave Arter",
    "author_email": "pypi@davea.me",
    "download_url": "https://files.pythonhosted.org/packages/11/33/d4116b38bf38b939880b3408e74e41467d5c4dfb25f8ab480090bf2dc192/mqttwrapper-0.1.0.tar.gz",
    "platform": null,
    "description": "mqttwrapper\n===========\n\nA little glue package to make it simple to quickly put together scripts that\nbridge MQTT and other libraries. See examples below.\n\nInstallation\n------------\n\nInstall from PyPI::\n\n  $ pip install mqttwrapper\n\nBy default ``paho-mqtt`` will be used as the MQTT library, but you can use\n``hbmqtt`` if you wish, though support for this is deprecated and will be\nremoved in the future. To install, use::\n\n  $ pip install mqttwrapper[hbmqtt]\n\nUsage\n-----\n\n``mqttwrapper.run_script`` handles the setup/maintenance of the MQTT connection\nand subscriptions to topics, and calls a callback function when messages are\nreceived. It can run in blocking mode where it will take care of the MQTT\nclient handling or in non blocking mode where a new thread takes care this\nleaving your main thread free for other things.\n\nThe simplest script looks something like this::\n\n  from mqttwrapper import run_script\n\n  def callback(topic, payload):\n      print(\"Received payload {} on topic {}\".format(payload, topic))\n\n  def main():\n      run_script(callback, broker=\"mqtt://127.0.0.1\", topics=[\"my/awesome/topic1\", \"another/awesome/topic2\"])\n\nor in non blocking mode::\n\n  def main():\n      run_script(callback, broker=\"mqtt://127.0.0.1\", topics=[\"my/awesome/topic1\", \"another/awesome/topic2\"], blocking=False)\n      while True:\n          echo \"Alive and kicking\"\n          time.sleep(1)\n\nAny extra keyword arguments passed to ``run_script`` are passed back to the\ncallback function when it's called::\n\n  from mqttwrapper import run_script\n\n  def callback(topic, payload, context, foo):\n      assert context == \"hello\"\n      assert foo == \"bar\"\n      print(\"Received payload {} on topic {}\".format(payload, topic))\n\n  def main():\n      run_script(callback, broker=\"mqtt://127.0.0.1\", topics=[\"my/awesome/topic1\", \"another/awesome/topic2\"], context=\"hello\", foo=\"bar\")\n\n\nIf you don't need any context passed to your callback, just the topic and\npayload of messages, you can run in 'importless' mode by creating a `callback`\nmodule which has a `callback` function defined, then execute the\n`mqttwrapper.run` module::\n\n  $ cat callback.py\n  def callback(topic, payload):\n      print(topic, payload)\n  \n  $ python -m mqttwrapper.run\n\nRetained messages\n-----------------\n\nYou can ignore MQTT retained messages by passing ``ignore_retained=True`` when\ncalling ``run_script``. NB this is currently not supported by the hbmqtt\nbackend.\n\nPublishing messages from the callback\n-------------------------------------\n\nSometimes your callback function might want to publish its own MQTT messages,\nperhaps in reply to or an acknowledgement of a received message. This is\npossible by returning an iterable of ``(topic, payload)`` tuples from the callback,\ne.g.::\n\n    def callback(topic, payload):\n      print(\"Received payload {} on topic {}\".format(payload, topic))\n      return [\n        (\"{}/ack\".format(topic), payload)\n      ]\n\n\n``mqttwrapper`` will take care of publishing these messages to the broker.\n\nThese tuples can optionally take the form ``(topic, payload, True)`` if you want\nthe published message to be marked as retained.\n\nConfiguration\n-------------\n\n``broker`` and ``topics`` can be omitted from the ``run_script`` call and\nenvironment variables used instead:\n\n- ``MQTT_BROKER``: MQTT broker to connect to, e.g. ``mqtt://127.0.0.1/``\n- ``MQTT_TOPICS``: Comma-separated list of topics to subscribe to, e.g. ``my/topic1,my/topic2``\n\nasyncio/hbmqtt\n--------------\n\nNB This feature is deprecated and will be removed in the future.\n\nThe asyncio-powered ``hbmqtt`` MQTT library can be used instead, if you like::\n\n  from mqttwrapper.hbmqtt_backend import run_script\n\n  async def callback(topic, payload):\n      print(\"Received payload {} on topic {}\".format(payload, topic))\n\n\nNote that your callback must be an awaitable in this case.\n\nYour callback may require context arguments which themselves are async objects\nor awaitables which poses a challenge: how to set these up outside of an asyncio\nevent loop before calling ``run_script``? In this case, you can pass a\n``context_callback`` awaitable as a kwarg to ``run_script``. This is run at the\nstart of the MQTT loop, and should return a dict which will be merged into the\nkwargs which are passed to your callback. For example::\n\n  from mqttwrapper.hbmqtt_backend import run_script\n\n  async def setup_db():\n    return {\n      \"query_db\": query_db\n    }\n\n  async def query_db(value):\n    # pretend this is some slow DB query, for example.\n    await asyncio.sleep(3)\n    return value * 2\n\n  async def callback(topic, payload, query_db):\n      db_result = await query_db(int(payload))\n      print(\"Received payload {} on topic {}, db result: {}\".format(payload, topic, db_result))\n\n  def main():\n      run_script(callback, context_callback=setup_db)\n\n\nNB hbmqtt's reconnection handling does not resubscribe to topics upon\nreconnection, and ``mqttwrapper`` does not yet work around this.\n\nExamples\n--------\n\n- rxv2mqtt_\n- tradfri-mqtt_ (uses asyncio)\n\n.. _rxv2mqtt: https://github.com/davea/rxv2mqtt/blob/master/main.py\n.. _tradfri-mqtt: https://github.com/davea/tradfri-mqtt/blob/master/main.py\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "MQTT utility scripts made easy",
    "version": "0.1.0",
    "project_urls": {
        "Homepage": "https://github.com/davea/mqttwrapper"
    },
    "split_keywords": [
        "mqtt"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e93828fc1bf6a42123d177ffe3290a352842dc1b676abdb92e9d900bc860fddf",
                "md5": "215fb11c35dd09dd1c15548fdf8cf8c4",
                "sha256": "5960f48e820cc5ef8153fc4b1f72164d2ef75d561efbde0ddafae59968f3fd16"
            },
            "downloads": -1,
            "filename": "mqttwrapper-0.1.0-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "215fb11c35dd09dd1c15548fdf8cf8c4",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 8346,
            "upload_time": "2024-03-02T15:04:19",
            "upload_time_iso_8601": "2024-03-02T15:04:19.552121Z",
            "url": "https://files.pythonhosted.org/packages/e9/38/28fc1bf6a42123d177ffe3290a352842dc1b676abdb92e9d900bc860fddf/mqttwrapper-0.1.0-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1133d4116b38bf38b939880b3408e74e41467d5c4dfb25f8ab480090bf2dc192",
                "md5": "50cfb90794db9b06e1eb44d98b63db78",
                "sha256": "3290dd20b7dbac1ede78089ce3d7db4d34a94b37e86a372992ceef59952e4677"
            },
            "downloads": -1,
            "filename": "mqttwrapper-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "50cfb90794db9b06e1eb44d98b63db78",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 5558,
            "upload_time": "2024-03-02T15:04:21",
            "upload_time_iso_8601": "2024-03-02T15:04:21.277277Z",
            "url": "https://files.pythonhosted.org/packages/11/33/d4116b38bf38b939880b3408e74e41467d5c4dfb25f8ab480090bf2dc192/mqttwrapper-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-02 15:04:21",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "davea",
    "github_project": "mqttwrapper",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "mqttwrapper"
}
        
Elapsed time: 7.38942s