mqttwrapper 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mqttwrapper
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: MQTT utility scripts made easy
5
5
  Home-page: https://github.com/davea/mqttwrapper
6
6
  Author: Dave Arter
@@ -17,8 +17,6 @@ Classifier: Programming Language :: Python :: 3.6
17
17
  Classifier: Programming Language :: Python :: 3.7
18
18
  License-File: LICENSE
19
19
  Requires-Dist: paho-mqtt>=2.0.0
20
- Provides-Extra: hbmqtt
21
- Requires-Dist: hbmqtt; extra == "hbmqtt"
22
20
  Dynamic: author
23
21
  Dynamic: author-email
24
22
  Dynamic: classifier
@@ -27,7 +25,6 @@ Dynamic: home-page
27
25
  Dynamic: keywords
28
26
  Dynamic: license
29
27
  Dynamic: license-file
30
- Dynamic: provides-extra
31
28
  Dynamic: requires-dist
32
29
  Dynamic: summary
33
30
 
@@ -44,11 +41,7 @@ Install from PyPI::
44
41
 
45
42
  $ pip install mqttwrapper
46
43
 
47
- By default ``paho-mqtt`` will be used as the MQTT library, but you can use
48
- ``hbmqtt`` if you wish, though support for this is deprecated and will be
49
- removed in the future. To install, use::
50
-
51
- $ pip install mqttwrapper[hbmqtt]
44
+ ``paho-mqtt`` is used as the underlying MQTT library.
52
45
 
53
46
  Usage
54
47
  -----
@@ -77,7 +70,7 @@ or in non blocking mode::
77
70
  echo "Alive and kicking"
78
71
  time.sleep(1)
79
72
 
80
- Any extra keyword arguments passed to ``run_script`` are passed back to the
73
+ Most extra keyword arguments passed to ``run_script`` are passed back to the
81
74
  callback function when it's called::
82
75
 
83
76
  from mqttwrapper import run_script
@@ -91,6 +84,18 @@ callback function when it's called::
91
84
  run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"], context="hello", foo="bar")
92
85
 
93
86
 
87
+ However some are reserved and will be consumed by ```run_script``` to configure how the MQTT connection behaves:
88
+
89
+
90
+ - ``broker`` (default ``MQTT_BROKER`` from environment, otherwise ``None``): broker URL, e.g ``mybroker``, ``mqtts://securebroker:8884``, ``mqtt://username:password@coolbroker.example.org``
91
+ - ``topics`` (default ``MQTT_TOPICS`` from environment, otherwise ``None``): list of topics to subscribe to
92
+ - ``ignore_retained`` (default ``False``): whether to ignore a received message if it was marked as retained
93
+ - ``blocking`` (default ``True``): run in blocking or threaded mode
94
+ - ``client_id`` (default ``"",``): client ID to use when connecting to broker
95
+ - ``clean_session`` (default ``True``): whether to use a clean session upon (re)connect, or resume previous session. ``client_id`` must be provided if ``True``
96
+ - ``qos`` (default ``0``): QoS to use for connection
97
+ - ``raise_exceptions`` (default ``False``): whether to raise exceptions that occur during callback execution
98
+
94
99
  If you don't need any context passed to your callback, just the topic and
95
100
  payload of messages, you can run in 'importless' mode by creating a `callback`
96
101
  module which has a `callback` function defined, then execute the
@@ -106,8 +111,7 @@ Retained messages
106
111
  -----------------
107
112
 
108
113
  You can ignore MQTT retained messages by passing ``ignore_retained=True`` when
109
- calling ``run_script``. NB this is currently not supported by the hbmqtt
110
- backend.
114
+ calling ``run_script``.
111
115
 
112
116
  Publishing messages from the callback
113
117
  -------------------------------------
@@ -129,6 +133,8 @@ e.g.::
129
133
  These tuples can optionally take the form ``(topic, payload, True)`` if you want
130
134
  the published message to be marked as retained.
131
135
 
136
+ NB any exceptions raised during execution of the callback will be logged and ignored, unless ``raise_exceptions=True`` is passed to ``run_script``.
137
+
132
138
  Configuration
133
139
  -------------
134
140
 
@@ -138,56 +144,10 @@ environment variables used instead:
138
144
  - ``MQTT_BROKER``: MQTT broker to connect to, e.g. ``mqtt://127.0.0.1/``
139
145
  - ``MQTT_TOPICS``: Comma-separated list of topics to subscribe to, e.g. ``my/topic1,my/topic2``
140
146
 
141
- asyncio/hbmqtt
142
- --------------
143
-
144
- NB This feature is deprecated and will be removed in the future.
145
-
146
- The asyncio-powered ``hbmqtt`` MQTT library can be used instead, if you like::
147
-
148
- from mqttwrapper.hbmqtt_backend import run_script
149
-
150
- async def callback(topic, payload):
151
- print("Received payload {} on topic {}".format(payload, topic))
152
-
153
-
154
- Note that your callback must be an awaitable in this case.
155
-
156
- Your callback may require context arguments which themselves are async objects
157
- or awaitables which poses a challenge: how to set these up outside of an asyncio
158
- event loop before calling ``run_script``? In this case, you can pass a
159
- ``context_callback`` awaitable as a kwarg to ``run_script``. This is run at the
160
- start of the MQTT loop, and should return a dict which will be merged into the
161
- kwargs which are passed to your callback. For example::
162
-
163
- from mqttwrapper.hbmqtt_backend import run_script
164
-
165
- async def setup_db():
166
- return {
167
- "query_db": query_db
168
- }
169
-
170
- async def query_db(value):
171
- # pretend this is some slow DB query, for example.
172
- await asyncio.sleep(3)
173
- return value * 2
174
-
175
- async def callback(topic, payload, query_db):
176
- db_result = await query_db(int(payload))
177
- print("Received payload {} on topic {}, db result: {}".format(payload, topic, db_result))
178
-
179
- def main():
180
- run_script(callback, context_callback=setup_db)
181
-
182
-
183
- NB hbmqtt's reconnection handling does not resubscribe to topics upon
184
- reconnection, and ``mqttwrapper`` does not yet work around this.
185
147
 
186
148
  Examples
187
149
  --------
188
150
 
189
151
  - rxv2mqtt_
190
- - tradfri-mqtt_ (uses asyncio)
191
152
 
192
153
  .. _rxv2mqtt: https://github.com/davea/rxv2mqtt/blob/master/main.py
193
- .. _tradfri-mqtt: https://github.com/davea/tradfri-mqtt/blob/master/main.py
@@ -11,11 +11,7 @@ Install from PyPI::
11
11
 
12
12
  $ pip install mqttwrapper
13
13
 
14
- By default ``paho-mqtt`` will be used as the MQTT library, but you can use
15
- ``hbmqtt`` if you wish, though support for this is deprecated and will be
16
- removed in the future. To install, use::
17
-
18
- $ pip install mqttwrapper[hbmqtt]
14
+ ``paho-mqtt`` is used as the underlying MQTT library.
19
15
 
20
16
  Usage
21
17
  -----
@@ -44,7 +40,7 @@ or in non blocking mode::
44
40
  echo "Alive and kicking"
45
41
  time.sleep(1)
46
42
 
47
- Any extra keyword arguments passed to ``run_script`` are passed back to the
43
+ Most extra keyword arguments passed to ``run_script`` are passed back to the
48
44
  callback function when it's called::
49
45
 
50
46
  from mqttwrapper import run_script
@@ -58,6 +54,18 @@ callback function when it's called::
58
54
  run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"], context="hello", foo="bar")
59
55
 
60
56
 
57
+ However some are reserved and will be consumed by ```run_script``` to configure how the MQTT connection behaves:
58
+
59
+
60
+ - ``broker`` (default ``MQTT_BROKER`` from environment, otherwise ``None``): broker URL, e.g ``mybroker``, ``mqtts://securebroker:8884``, ``mqtt://username:password@coolbroker.example.org``
61
+ - ``topics`` (default ``MQTT_TOPICS`` from environment, otherwise ``None``): list of topics to subscribe to
62
+ - ``ignore_retained`` (default ``False``): whether to ignore a received message if it was marked as retained
63
+ - ``blocking`` (default ``True``): run in blocking or threaded mode
64
+ - ``client_id`` (default ``"",``): client ID to use when connecting to broker
65
+ - ``clean_session`` (default ``True``): whether to use a clean session upon (re)connect, or resume previous session. ``client_id`` must be provided if ``True``
66
+ - ``qos`` (default ``0``): QoS to use for connection
67
+ - ``raise_exceptions`` (default ``False``): whether to raise exceptions that occur during callback execution
68
+
61
69
  If you don't need any context passed to your callback, just the topic and
62
70
  payload of messages, you can run in 'importless' mode by creating a `callback`
63
71
  module which has a `callback` function defined, then execute the
@@ -73,8 +81,7 @@ Retained messages
73
81
  -----------------
74
82
 
75
83
  You can ignore MQTT retained messages by passing ``ignore_retained=True`` when
76
- calling ``run_script``. NB this is currently not supported by the hbmqtt
77
- backend.
84
+ calling ``run_script``.
78
85
 
79
86
  Publishing messages from the callback
80
87
  -------------------------------------
@@ -96,6 +103,8 @@ e.g.::
96
103
  These tuples can optionally take the form ``(topic, payload, True)`` if you want
97
104
  the published message to be marked as retained.
98
105
 
106
+ NB any exceptions raised during execution of the callback will be logged and ignored, unless ``raise_exceptions=True`` is passed to ``run_script``.
107
+
99
108
  Configuration
100
109
  -------------
101
110
 
@@ -105,56 +114,10 @@ environment variables used instead:
105
114
  - ``MQTT_BROKER``: MQTT broker to connect to, e.g. ``mqtt://127.0.0.1/``
106
115
  - ``MQTT_TOPICS``: Comma-separated list of topics to subscribe to, e.g. ``my/topic1,my/topic2``
107
116
 
108
- asyncio/hbmqtt
109
- --------------
110
-
111
- NB This feature is deprecated and will be removed in the future.
112
-
113
- The asyncio-powered ``hbmqtt`` MQTT library can be used instead, if you like::
114
-
115
- from mqttwrapper.hbmqtt_backend import run_script
116
-
117
- async def callback(topic, payload):
118
- print("Received payload {} on topic {}".format(payload, topic))
119
-
120
-
121
- Note that your callback must be an awaitable in this case.
122
-
123
- Your callback may require context arguments which themselves are async objects
124
- or awaitables which poses a challenge: how to set these up outside of an asyncio
125
- event loop before calling ``run_script``? In this case, you can pass a
126
- ``context_callback`` awaitable as a kwarg to ``run_script``. This is run at the
127
- start of the MQTT loop, and should return a dict which will be merged into the
128
- kwargs which are passed to your callback. For example::
129
-
130
- from mqttwrapper.hbmqtt_backend import run_script
131
-
132
- async def setup_db():
133
- return {
134
- "query_db": query_db
135
- }
136
-
137
- async def query_db(value):
138
- # pretend this is some slow DB query, for example.
139
- await asyncio.sleep(3)
140
- return value * 2
141
-
142
- async def callback(topic, payload, query_db):
143
- db_result = await query_db(int(payload))
144
- print("Received payload {} on topic {}, db result: {}".format(payload, topic, db_result))
145
-
146
- def main():
147
- run_script(callback, context_callback=setup_db)
148
-
149
-
150
- NB hbmqtt's reconnection handling does not resubscribe to topics upon
151
- reconnection, and ``mqttwrapper`` does not yet work around this.
152
117
 
153
118
  Examples
154
119
  --------
155
120
 
156
121
  - rxv2mqtt_
157
- - tradfri-mqtt_ (uses asyncio)
158
122
 
159
123
  .. _rxv2mqtt: https://github.com/davea/rxv2mqtt/blob/master/main.py
160
- .. _tradfri-mqtt: https://github.com/davea/tradfri-mqtt/blob/master/main.py
@@ -1,16 +1,23 @@
1
- import os
2
1
  import logging
3
- import paho.mqtt.client as mqtt
2
+ import os
4
3
  import threading
4
+ from urllib.parse import urlsplit
5
+
6
+ import paho.mqtt.client as mqtt
5
7
 
6
8
  log = logging.getLogger("mqttwrapper.paho_backend")
7
9
 
8
10
  def on_connect(client, userdata, flags, rc):
9
11
  log.debug("Connected")
10
12
  for topic in userdata['topics']:
11
- client.subscribe(topic)
13
+ client.subscribe(topic, qos=userdata['qos'])
12
14
  log.debug("Subscribed to %s", topic)
13
15
 
16
+ def on_disconnect(client, userdata, rc):
17
+ if rc != mqtt.MQTT_ERR_SUCCESS:
18
+ log.warning("Lost broker connection (%s), reconnecting",
19
+ mqtt.error_string(rc))
20
+
14
21
  def on_message(client, userdata, msg):
15
22
  log.debug("Received message on %s", msg.topic)
16
23
  if msg.retain and userdata['ignore_retained']:
@@ -19,8 +26,10 @@ def on_message(client, userdata, msg):
19
26
  replies = None
20
27
  try:
21
28
  replies = userdata['callback'](msg.topic, msg.payload, **userdata['kwargs'])
22
- except Exception as e:
23
- log.error("Callback caused exception", exc_info = True)
29
+ except Exception:
30
+ if userdata['raise_exceptions']:
31
+ raise
32
+ log.exception("Callback caused exception")
24
33
  log.debug("Callback completed.")
25
34
  if replies is not None:
26
35
  replies = list(replies)
@@ -35,28 +44,54 @@ def on_message(client, userdata, msg):
35
44
  client.publish(topic, payload, retain=retain)
36
45
  log.debug("Published '%s' to %s (retain: %s)", payload, topic, retain)
37
46
 
47
+ def parse_broker(broker):
48
+ if "//" not in broker:
49
+ broker = "mqtt://" + broker
50
+ url = urlsplit(broker)
51
+ if url.scheme not in ("mqtt", "mqtts"):
52
+ raise ValueError(f"Unsupported broker URL scheme: {url.scheme}")
53
+ tls = url.scheme == "mqtts"
54
+ port = url.port or (8883 if tls else 1883)
55
+ return url.hostname, port, tls, url.username, url.password
56
+
38
57
  def mqtt_thread(client):
39
58
  client.loop_forever()
40
59
 
41
- def run_script(callback, broker=None, topics=None, ignore_retained=False, blocking=True, **kwargs):
60
+ def run_script(callback, broker=None, topics=None, ignore_retained=False, blocking=True,
61
+ client_id="", clean_session=True, qos=0, raise_exceptions=False, **kwargs):
42
62
  if not broker:
43
63
  broker = os.environ['MQTT_BROKER']
44
64
  if not topics:
45
65
  topics = os.environ['MQTT_TOPICS'].split(",")
66
+ if not clean_session and not client_id:
67
+ raise ValueError("client_id is required when using clean_session")
68
+ if raise_exceptions and not blocking:
69
+ raise ValueError("raise_exceptions can't be used with blocking=False")
46
70
 
47
71
  userdata = {
48
72
  'topics': topics,
73
+ 'qos': qos,
49
74
  'callback': callback,
50
75
  'ignore_retained': ignore_retained,
76
+ 'raise_exceptions': raise_exceptions,
51
77
  'kwargs': kwargs
52
78
  }
53
79
 
54
- client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, userdata=userdata)
80
+ client = mqtt.Client(
81
+ mqtt.CallbackAPIVersion.VERSION1,
82
+ client_id=client_id,
83
+ clean_session=clean_session,
84
+ userdata=userdata,
85
+ )
55
86
  client.on_connect = on_connect
56
87
  client.on_message = on_message
57
- if "//" in broker: # mqtt:// prefix is optional (NB mqtts:// is not supported)
58
- broker = broker.split("//")[1]
59
- client.connect(broker)
88
+ client.on_disconnect = on_disconnect
89
+ host, port, tls, username, password = parse_broker(broker)
90
+ if tls:
91
+ client.tls_set()
92
+ if username:
93
+ client.username_pw_set(username, password)
94
+ client.connect(host, port)
60
95
  if blocking:
61
96
  client.loop_forever()
62
97
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mqttwrapper
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: MQTT utility scripts made easy
5
5
  Home-page: https://github.com/davea/mqttwrapper
6
6
  Author: Dave Arter
@@ -17,8 +17,6 @@ Classifier: Programming Language :: Python :: 3.6
17
17
  Classifier: Programming Language :: Python :: 3.7
18
18
  License-File: LICENSE
19
19
  Requires-Dist: paho-mqtt>=2.0.0
20
- Provides-Extra: hbmqtt
21
- Requires-Dist: hbmqtt; extra == "hbmqtt"
22
20
  Dynamic: author
23
21
  Dynamic: author-email
24
22
  Dynamic: classifier
@@ -27,7 +25,6 @@ Dynamic: home-page
27
25
  Dynamic: keywords
28
26
  Dynamic: license
29
27
  Dynamic: license-file
30
- Dynamic: provides-extra
31
28
  Dynamic: requires-dist
32
29
  Dynamic: summary
33
30
 
@@ -44,11 +41,7 @@ Install from PyPI::
44
41
 
45
42
  $ pip install mqttwrapper
46
43
 
47
- By default ``paho-mqtt`` will be used as the MQTT library, but you can use
48
- ``hbmqtt`` if you wish, though support for this is deprecated and will be
49
- removed in the future. To install, use::
50
-
51
- $ pip install mqttwrapper[hbmqtt]
44
+ ``paho-mqtt`` is used as the underlying MQTT library.
52
45
 
53
46
  Usage
54
47
  -----
@@ -77,7 +70,7 @@ or in non blocking mode::
77
70
  echo "Alive and kicking"
78
71
  time.sleep(1)
79
72
 
80
- Any extra keyword arguments passed to ``run_script`` are passed back to the
73
+ Most extra keyword arguments passed to ``run_script`` are passed back to the
81
74
  callback function when it's called::
82
75
 
83
76
  from mqttwrapper import run_script
@@ -91,6 +84,18 @@ callback function when it's called::
91
84
  run_script(callback, broker="mqtt://127.0.0.1", topics=["my/awesome/topic1", "another/awesome/topic2"], context="hello", foo="bar")
92
85
 
93
86
 
87
+ However some are reserved and will be consumed by ```run_script``` to configure how the MQTT connection behaves:
88
+
89
+
90
+ - ``broker`` (default ``MQTT_BROKER`` from environment, otherwise ``None``): broker URL, e.g ``mybroker``, ``mqtts://securebroker:8884``, ``mqtt://username:password@coolbroker.example.org``
91
+ - ``topics`` (default ``MQTT_TOPICS`` from environment, otherwise ``None``): list of topics to subscribe to
92
+ - ``ignore_retained`` (default ``False``): whether to ignore a received message if it was marked as retained
93
+ - ``blocking`` (default ``True``): run in blocking or threaded mode
94
+ - ``client_id`` (default ``"",``): client ID to use when connecting to broker
95
+ - ``clean_session`` (default ``True``): whether to use a clean session upon (re)connect, or resume previous session. ``client_id`` must be provided if ``True``
96
+ - ``qos`` (default ``0``): QoS to use for connection
97
+ - ``raise_exceptions`` (default ``False``): whether to raise exceptions that occur during callback execution
98
+
94
99
  If you don't need any context passed to your callback, just the topic and
95
100
  payload of messages, you can run in 'importless' mode by creating a `callback`
96
101
  module which has a `callback` function defined, then execute the
@@ -106,8 +111,7 @@ Retained messages
106
111
  -----------------
107
112
 
108
113
  You can ignore MQTT retained messages by passing ``ignore_retained=True`` when
109
- calling ``run_script``. NB this is currently not supported by the hbmqtt
110
- backend.
114
+ calling ``run_script``.
111
115
 
112
116
  Publishing messages from the callback
113
117
  -------------------------------------
@@ -129,6 +133,8 @@ e.g.::
129
133
  These tuples can optionally take the form ``(topic, payload, True)`` if you want
130
134
  the published message to be marked as retained.
131
135
 
136
+ NB any exceptions raised during execution of the callback will be logged and ignored, unless ``raise_exceptions=True`` is passed to ``run_script``.
137
+
132
138
  Configuration
133
139
  -------------
134
140
 
@@ -138,56 +144,10 @@ environment variables used instead:
138
144
  - ``MQTT_BROKER``: MQTT broker to connect to, e.g. ``mqtt://127.0.0.1/``
139
145
  - ``MQTT_TOPICS``: Comma-separated list of topics to subscribe to, e.g. ``my/topic1,my/topic2``
140
146
 
141
- asyncio/hbmqtt
142
- --------------
143
-
144
- NB This feature is deprecated and will be removed in the future.
145
-
146
- The asyncio-powered ``hbmqtt`` MQTT library can be used instead, if you like::
147
-
148
- from mqttwrapper.hbmqtt_backend import run_script
149
-
150
- async def callback(topic, payload):
151
- print("Received payload {} on topic {}".format(payload, topic))
152
-
153
-
154
- Note that your callback must be an awaitable in this case.
155
-
156
- Your callback may require context arguments which themselves are async objects
157
- or awaitables which poses a challenge: how to set these up outside of an asyncio
158
- event loop before calling ``run_script``? In this case, you can pass a
159
- ``context_callback`` awaitable as a kwarg to ``run_script``. This is run at the
160
- start of the MQTT loop, and should return a dict which will be merged into the
161
- kwargs which are passed to your callback. For example::
162
-
163
- from mqttwrapper.hbmqtt_backend import run_script
164
-
165
- async def setup_db():
166
- return {
167
- "query_db": query_db
168
- }
169
-
170
- async def query_db(value):
171
- # pretend this is some slow DB query, for example.
172
- await asyncio.sleep(3)
173
- return value * 2
174
-
175
- async def callback(topic, payload, query_db):
176
- db_result = await query_db(int(payload))
177
- print("Received payload {} on topic {}, db result: {}".format(payload, topic, db_result))
178
-
179
- def main():
180
- run_script(callback, context_callback=setup_db)
181
-
182
-
183
- NB hbmqtt's reconnection handling does not resubscribe to topics upon
184
- reconnection, and ``mqttwrapper`` does not yet work around this.
185
147
 
186
148
  Examples
187
149
  --------
188
150
 
189
151
  - rxv2mqtt_
190
- - tradfri-mqtt_ (uses asyncio)
191
152
 
192
153
  .. _rxv2mqtt: https://github.com/davea/rxv2mqtt/blob/master/main.py
193
- .. _tradfri-mqtt: https://github.com/davea/tradfri-mqtt/blob/master/main.py
@@ -2,7 +2,6 @@ LICENSE
2
2
  README.rst
3
3
  setup.py
4
4
  mqttwrapper/__init__.py
5
- mqttwrapper/hbmqtt_backend.py
6
5
  mqttwrapper/paho_backend.py
7
6
  mqttwrapper/run.py
8
7
  mqttwrapper.egg-info/PKG-INFO
@@ -1,4 +1 @@
1
1
  paho-mqtt>=2.0.0
2
-
3
- [hbmqtt]
4
- hbmqtt
@@ -1,14 +1,15 @@
1
- from setuptools import setup, find_packages
2
1
  from codecs import open
3
2
  from os import path
4
3
 
4
+ from setuptools import find_packages, setup
5
+
5
6
  here = path.abspath(path.dirname(__file__))
6
7
  with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
7
8
  long_description = f.read()
8
9
 
9
10
  setup(
10
11
  name='mqttwrapper',
11
- version='0.2.0',
12
+ version='0.3.0',
12
13
  description='MQTT utility scripts made easy',
13
14
  long_description=long_description,
14
15
  url='https://github.com/davea/mqttwrapper',
@@ -28,7 +29,4 @@ setup(
28
29
  keywords='mqtt',
29
30
  packages=find_packages(),
30
31
  install_requires=['paho-mqtt>=2.0.0'],
31
- extras_require={
32
- 'hbmqtt': ['hbmqtt'],
33
- },
34
32
  )
@@ -1,43 +0,0 @@
1
- import os
2
- import logging
3
- import asyncio
4
- from warnings import warn
5
-
6
- from hbmqtt.client import MQTTClient, ClientException
7
- from hbmqtt.mqtt.constants import QOS_0
8
-
9
- log = logging.getLogger("mqttwrapper.hbmqtt_backend")
10
-
11
- warn("hbmqtt backend is deprecated and will be removed in the future.", DeprecationWarning)
12
- log.warn("hbmqtt backend is deprecated and will be removed in the future.")
13
-
14
- async def mqtt_loop(broker, topics, callback, context_callback, **kwargs):
15
- if context_callback is not None:
16
- kwargs.update(await context_callback())
17
- client = MQTTClient()
18
- await client.connect(broker, cleansession=True)
19
- log.debug("Connected")
20
- await client.subscribe([(topic, QOS_0) for topic in topics])
21
- log.debug("Subscribed to %s", topics)
22
- try:
23
- while True:
24
- message = await client.deliver_message()
25
- packet = message.publish_packet
26
- topic = packet.variable_header.topic_name
27
- payload = bytes(packet.payload.data)
28
- replies = await callback(topic, payload, **kwargs)
29
- if replies is not None:
30
- for reply_topic, reply_payload in replies:
31
- await client.publish(reply_topic, reply_payload)
32
- except ClientException:
33
- log.exception("hbmqtt.client.ClientException:")
34
- raise
35
-
36
-
37
- def run_script(callback, broker=None, topics=None, context_callback=None, **kwargs):
38
- if not broker:
39
- broker = os.environ['MQTT_BROKER']
40
- if not topics:
41
- topics = os.environ['MQTT_TOPICS'].split(",")
42
-
43
- asyncio.get_event_loop().run_until_complete(mqtt_loop(broker, topics, callback, context_callback, **kwargs))
File without changes
File without changes