dbus2mqtt 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl
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.
Potentially problematic release.
This version of dbus2mqtt might be problematic. Click here for more details.
- dbus2mqtt/config/__init__.py +16 -10
- dbus2mqtt/config/jsonarparse.py +23 -17
- dbus2mqtt/dbus/dbus_client.py +2 -2
- dbus2mqtt/flow/flow_processor.py +1 -1
- dbus2mqtt/mqtt/mqtt_client.py +2 -2
- dbus2mqtt/template/templating.py +27 -3
- {dbus2mqtt-0.5.0.dist-info → dbus2mqtt-0.5.2.dist-info}/METADATA +9 -9
- {dbus2mqtt-0.5.0.dist-info → dbus2mqtt-0.5.2.dist-info}/RECORD +11 -11
- {dbus2mqtt-0.5.0.dist-info → dbus2mqtt-0.5.2.dist-info}/WHEEL +0 -0
- {dbus2mqtt-0.5.0.dist-info → dbus2mqtt-0.5.2.dist-info}/entry_points.txt +0 -0
- {dbus2mqtt-0.5.0.dist-info → dbus2mqtt-0.5.2.dist-info}/licenses/LICENSE +0 -0
dbus2mqtt/config/__init__.py
CHANGED
|
@@ -3,9 +3,9 @@ import uuid
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Any, Literal
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from jsonargparse.typing import SecretStr
|
|
9
9
|
|
|
10
10
|
from dbus2mqtt.template.templating import TemplateEngine
|
|
11
11
|
|
|
@@ -98,10 +98,15 @@ class FlowTriggerMqttMessageConfig:
|
|
|
98
98
|
return template_engine.render_template(self.filter, bool, trigger_context)
|
|
99
99
|
return True
|
|
100
100
|
|
|
101
|
-
FlowTriggerConfig =
|
|
102
|
-
FlowTriggerScheduleConfig
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
FlowTriggerConfig = (
|
|
102
|
+
FlowTriggerScheduleConfig
|
|
103
|
+
| FlowTriggerDbusSignalConfig
|
|
104
|
+
| FlowTriggerBusNameAddedConfig
|
|
105
|
+
| FlowTriggerBusNameRemovedConfig
|
|
106
|
+
| FlowTriggerObjectAddedConfig
|
|
107
|
+
| FlowTriggerObjectRemovedConfig
|
|
108
|
+
| FlowTriggerMqttMessageConfig
|
|
109
|
+
)
|
|
105
110
|
|
|
106
111
|
@dataclass
|
|
107
112
|
class FlowActionContextSetConfig:
|
|
@@ -124,10 +129,11 @@ class FlowActionLogConfig:
|
|
|
124
129
|
type: Literal["log"] = "log"
|
|
125
130
|
level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO"
|
|
126
131
|
|
|
127
|
-
FlowActionConfig =
|
|
128
|
-
FlowActionMqttPublishConfig
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
FlowActionConfig = (
|
|
133
|
+
FlowActionMqttPublishConfig
|
|
134
|
+
| FlowActionContextSetConfig
|
|
135
|
+
| FlowActionLogConfig
|
|
136
|
+
)
|
|
131
137
|
|
|
132
138
|
@dataclass
|
|
133
139
|
class FlowConfig:
|
dbus2mqtt/config/jsonarparse.py
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
import jsonargparse
|
|
2
4
|
|
|
5
|
+
from yaml import YAMLError
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
v = stream.strip()
|
|
7
|
+
default_yaml_loader = jsonargparse.get_loader("yaml")
|
|
8
|
+
def _custom_yaml_load(stream: str) -> Any:
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
# Without this, str:"{'PlaybackStatus': 'Off'}" would become dict:{'PlaybackStatus': False}
|
|
10
|
-
if v in ['on', 'On', 'off', 'Off', 'TRUE', 'FALSE', 'True', 'False']:
|
|
11
|
-
return stream
|
|
10
|
+
v = stream.strip()
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if "#" not in first_line and ("{{" in first_line or first_line.startswith("{%")):
|
|
18
|
-
return stream
|
|
12
|
+
# jsonargparse tries to parse yaml 1.1 boolean like values
|
|
13
|
+
# Without this, str:"{'PlaybackStatus': 'Off'}" would become dict:{'PlaybackStatus': False}
|
|
14
|
+
if v in ['on', 'On', 'off', 'Off', 'TRUE', 'FALSE', 'True', 'False']:
|
|
15
|
+
return stream
|
|
19
16
|
|
|
20
17
|
# Delegate to default yaml loader from jsonargparse
|
|
21
|
-
|
|
22
|
-
return yaml_loader(stream)
|
|
18
|
+
return default_yaml_loader(stream)
|
|
23
19
|
|
|
24
20
|
def new_argument_parser() -> jsonargparse.ArgumentParser:
|
|
25
21
|
|
|
26
22
|
# register out custom yaml loader for jsonargparse
|
|
27
|
-
jsonargparse.set_loader(
|
|
23
|
+
jsonargparse.set_loader(
|
|
24
|
+
mode="yaml_custom",
|
|
25
|
+
loader_fn=_custom_yaml_load,
|
|
26
|
+
exceptions=(YAMLError,),
|
|
27
|
+
json_superset=True
|
|
28
|
+
)
|
|
28
29
|
|
|
29
30
|
# unless specified otherwise, load config from config.yaml
|
|
30
|
-
parser = jsonargparse.ArgumentParser(
|
|
31
|
+
parser = jsonargparse.ArgumentParser(
|
|
32
|
+
default_config_files=["config.yaml"],
|
|
33
|
+
default_env=True,
|
|
34
|
+
env_prefix=False,
|
|
35
|
+
parser_mode="yaml_custom"
|
|
36
|
+
)
|
|
31
37
|
|
|
32
38
|
return parser
|
dbus2mqtt/dbus/dbus_client.py
CHANGED
|
@@ -686,7 +686,7 @@ class DbusClient:
|
|
|
686
686
|
try:
|
|
687
687
|
await self._on_mqtt_msg(msg, hints)
|
|
688
688
|
except Exception as e:
|
|
689
|
-
logger.warning(f"mqtt_receive_queue_processor_task: Exception {e}", exc_info=True)
|
|
689
|
+
logger.warning(f"mqtt_receive_queue_processor_task: Exception: {e}", exc_info=True)
|
|
690
690
|
finally:
|
|
691
691
|
self.event_broker.mqtt_receive_queue.async_q.task_done()
|
|
692
692
|
|
|
@@ -735,7 +735,7 @@ class DbusClient:
|
|
|
735
735
|
|
|
736
736
|
await self.event_broker.flow_trigger_queue.async_q.put(trigger_message)
|
|
737
737
|
except Exception as e:
|
|
738
|
-
logger.warning(f"dbus_signal_queue_processor_task: Exception {e}", exc_info=True)
|
|
738
|
+
logger.warning(f"dbus_signal_queue_processor_task: Exception: {e}", exc_info=True)
|
|
739
739
|
|
|
740
740
|
async def _handle_dbus_object_lifecycle_signal(self, message: dbus_message.Message):
|
|
741
741
|
|
dbus2mqtt/flow/flow_processor.py
CHANGED
|
@@ -187,7 +187,7 @@ class FlowProcessor:
|
|
|
187
187
|
if "was not provided by any .service files" in str(e):
|
|
188
188
|
log_level = logging.DEBUG
|
|
189
189
|
|
|
190
|
-
logger.log(log_level, f"flow_processor_task: Exception {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
190
|
+
logger.log(log_level, f"flow_processor_task: Exception: {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
191
191
|
finally:
|
|
192
192
|
self.event_broker.flow_trigger_queue.async_q.task_done()
|
|
193
193
|
|
dbus2mqtt/mqtt/mqtt_client.py
CHANGED
|
@@ -84,7 +84,7 @@ class MqttClient:
|
|
|
84
84
|
except Exception as e:
|
|
85
85
|
# In case failing uri reads, we still publish an empty msg to avoid stale data
|
|
86
86
|
payload = None
|
|
87
|
-
logger.warning(f"mqtt_publish_queue_processor_task: Exception {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
87
|
+
logger.warning(f"mqtt_publish_queue_processor_task: Exception: {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
88
88
|
|
|
89
89
|
payload_log_msg = payload if isinstance(payload, str) else msg.payload
|
|
90
90
|
logger.debug(f"mqtt_publish_queue_processor_task: topic={msg.topic}, type={payload.__class__}, payload={payload_log_msg}")
|
|
@@ -107,7 +107,7 @@ class MqttClient:
|
|
|
107
107
|
first_message = False
|
|
108
108
|
|
|
109
109
|
except Exception as e:
|
|
110
|
-
logger.warning(f"mqtt_publish_queue_processor_task: Exception {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
110
|
+
logger.warning(f"mqtt_publish_queue_processor_task: Exception: {e}", exc_info=logger.isEnabledFor(logging.DEBUG))
|
|
111
111
|
finally:
|
|
112
112
|
self.event_broker.mqtt_publish_queue.async_q.task_done()
|
|
113
113
|
|
dbus2mqtt/template/templating.py
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import urllib.parse
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
+
from importlib.metadata import version
|
|
4
5
|
from typing import Any, TypeVar
|
|
5
6
|
|
|
6
|
-
from jinja2 import
|
|
7
|
+
from jinja2 import (
|
|
8
|
+
BaseLoader,
|
|
9
|
+
StrictUndefined,
|
|
10
|
+
TemplateError,
|
|
11
|
+
TemplateRuntimeError,
|
|
12
|
+
UndefinedError,
|
|
13
|
+
)
|
|
7
14
|
from jinja2.nativetypes import NativeEnvironment
|
|
8
15
|
from jinja2_ansible_filters import AnsibleCoreFiltersExtension
|
|
9
16
|
|
|
@@ -18,6 +25,9 @@ class TemplateEngine:
|
|
|
18
25
|
engine_globals = {}
|
|
19
26
|
engine_globals['now'] = datetime.now
|
|
20
27
|
engine_globals['urldecode'] = urldecode
|
|
28
|
+
engine_globals['dbus2mqtt'] = {
|
|
29
|
+
'version': version('dbus2mqtt')
|
|
30
|
+
}
|
|
21
31
|
|
|
22
32
|
engine_filters = {}
|
|
23
33
|
engine_filters['urldecode'] = urldecode
|
|
@@ -69,10 +79,17 @@ class TemplateEngine:
|
|
|
69
79
|
|
|
70
80
|
if isinstance(templatable, str):
|
|
71
81
|
try:
|
|
72
|
-
|
|
82
|
+
template = self.jinja2_env.from_string(templatable)
|
|
73
83
|
except TemplateError as e:
|
|
74
84
|
raise TemplateError(f"Error compiling template, template={templatable}: {e}") from e
|
|
75
85
|
|
|
86
|
+
try:
|
|
87
|
+
res = template.render(**context)
|
|
88
|
+
str(res) # access value to trigger jinja UndefinedError
|
|
89
|
+
return res
|
|
90
|
+
except UndefinedError as e:
|
|
91
|
+
raise TemplateRuntimeError(f"Error rendering template, template={templatable}: {e}") from e
|
|
92
|
+
|
|
76
93
|
elif isinstance(templatable, dict):
|
|
77
94
|
res = {}
|
|
78
95
|
for k, v in templatable.items():
|
|
@@ -95,10 +112,17 @@ class TemplateEngine:
|
|
|
95
112
|
|
|
96
113
|
if isinstance(templatable, str):
|
|
97
114
|
try:
|
|
98
|
-
|
|
115
|
+
template = self.jinja2_async_env.from_string(templatable)
|
|
99
116
|
except TemplateError as e:
|
|
100
117
|
raise TemplateError(f"Error compiling template, template={templatable}: {e}") from e
|
|
101
118
|
|
|
119
|
+
try:
|
|
120
|
+
res = await template.render_async(**context)
|
|
121
|
+
str(res) # access value to trigger jinja UndefinedError
|
|
122
|
+
return res
|
|
123
|
+
except UndefinedError as e:
|
|
124
|
+
raise TemplateRuntimeError(f"Error rendering template, template={templatable}: {e}") from e
|
|
125
|
+
|
|
102
126
|
elif isinstance(templatable, dict):
|
|
103
127
|
res = {}
|
|
104
128
|
for k, v in templatable.items():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbus2mqtt
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: General purpose DBus to MQTT bridge - expose signals, methods and properties over MQTT - featuring jinja based templating, payload enrichment and MPRIS / BlueZ / Home Assistant ready examples
|
|
5
5
|
Project-URL: Documentation, https://jwnmulder.github.io/dbus2mqtt
|
|
6
6
|
Project-URL: Source, https://github.com/jwnmulder/dbus2mqtt
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
21
|
Classifier: Topic :: Home Automation
|
|
21
22
|
Requires-Python: >=3.10
|
|
22
23
|
Requires-Dist: apscheduler>=3.11.0
|
|
@@ -27,7 +28,6 @@ Requires-Dist: jinja2-ansible-filters>=1.3.2
|
|
|
27
28
|
Requires-Dist: jinja2>=3.1.6
|
|
28
29
|
Requires-Dist: jsonargparse>=4.38.0
|
|
29
30
|
Requires-Dist: paho-mqtt>=2.1.0
|
|
30
|
-
Requires-Dist: pydantic>=2.11.3
|
|
31
31
|
Requires-Dist: python-dotenv>=1.1.0
|
|
32
32
|
Requires-Dist: pyyaml>=6.0.2
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
@@ -51,7 +51,7 @@ This makes it easy to integrate Linux desktop services or system signals into MQ
|
|
|
51
51
|
|
|
52
52
|
**dbus2mqtt** is considered stable for the use-cases it has been tested against, and is actively being developed. Documentation is continuously being improved.
|
|
53
53
|
|
|
54
|
-
Initial testing has focused on MPRIS integration. A table of tested MPRIS players and their supported methods can be found on [Mediaplayer integration with Home Assistant](https://jwnmulder.github.io/dbus2mqtt/examples/home_assistant_media_player
|
|
54
|
+
Initial testing has focused on MPRIS integration. A table of tested MPRIS players and their supported methods can be found on [Mediaplayer integration with Home Assistant](https://jwnmulder.github.io/dbus2mqtt/examples/home_assistant_media_player/)
|
|
55
55
|
|
|
56
56
|
## Getting started with dbus2mqtt
|
|
57
57
|
|
|
@@ -101,16 +101,16 @@ python -m pip install dbus2mqtt
|
|
|
101
101
|
dbus2mqtt --config config.yaml
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
See [setup](https://jwnmulder.github.io/dbus2mqtt/setup
|
|
104
|
+
See [setup](https://jwnmulder.github.io/dbus2mqtt/setup/) for more installation options and configuration details.
|
|
105
105
|
|
|
106
106
|
## Examples
|
|
107
107
|
|
|
108
|
-
More dbus2mqtt examples can be found in the [examples](https://jwnmulder.github.io/dbus2mqtt/examples/
|
|
109
|
-
The most complete one being [Mediaplayer integration with Home Assistant](https://jwnmulder.github.io/dbus2mqtt/examples/home_assistant_media_player
|
|
108
|
+
More dbus2mqtt examples can be found in the [examples](https://jwnmulder.github.io/dbus2mqtt/examples/) section.
|
|
109
|
+
The most complete one being [Mediaplayer integration with Home Assistant](https://jwnmulder.github.io/dbus2mqtt/examples/home_assistant_media_player/)
|
|
110
110
|
|
|
111
111
|
## Exposing dbus methods, properties and signals
|
|
112
112
|
|
|
113
|
-
See [subscriptions](https://jwnmulder.github.io/dbus2mqtt/subscriptions
|
|
113
|
+
See [subscriptions](https://jwnmulder.github.io/dbus2mqtt/subscriptions/) for documentation on calling methods, setting properties and exposing D-Bus signals to MQTT. When configured, D-Bus methods can be invoked by publishing a message like
|
|
114
114
|
|
|
115
115
|
```json
|
|
116
116
|
{
|
|
@@ -120,6 +120,6 @@ See [subscriptions](https://jwnmulder.github.io/dbus2mqtt/subscriptions.html) fo
|
|
|
120
120
|
|
|
121
121
|
## Flows and Jinja based templating
|
|
122
122
|
|
|
123
|
-
For more advanced use-cases, dbus2mqtt has support for flows and Jinja2 based templates. A reference of all supported flow triggers and actions can be found on [flows](https://jwnmulder.github.io/dbus2mqtt/flows/
|
|
123
|
+
For more advanced use-cases, dbus2mqtt has support for flows and Jinja2 based templates. A reference of all supported flow triggers and actions can be found on [flows](https://jwnmulder.github.io/dbus2mqtt/flows/)
|
|
124
124
|
|
|
125
|
-
Jinja templating documentation can be found here: [templating](templating/
|
|
125
|
+
Jinja templating documentation can be found here: [templating](https://jwnmulder.github.io/dbus2mqtt/templating/)
|
|
@@ -2,23 +2,23 @@ dbus2mqtt/__init__.py,sha256=VunubKEH4_lne9Ttd2YRpyXjZMIAzyD2eiJ2sfvvTFU,362
|
|
|
2
2
|
dbus2mqtt/__main__.py,sha256=NAoa3nwgBSQI22eWzzRx61SIDThDwXmUofWWZU3_4-Q,71
|
|
3
3
|
dbus2mqtt/event_broker.py,sha256=8Iw1PNpH4IxQbpcFtNvPDc8_M8kuGarN6Kvz_a2aFfc,1468
|
|
4
4
|
dbus2mqtt/main.py,sha256=Kr2LRVxWcPDtNwCj8Eqz9TxtGLAVrV4q0nizKh1pLXc,4539
|
|
5
|
-
dbus2mqtt/config/__init__.py,sha256=
|
|
6
|
-
dbus2mqtt/config/jsonarparse.py,sha256
|
|
7
|
-
dbus2mqtt/dbus/dbus_client.py,sha256=
|
|
5
|
+
dbus2mqtt/config/__init__.py,sha256=daqVzuSxNnUNKtMoMYs73AdlkfS6goXUsxF1wnKi7y0,5894
|
|
6
|
+
dbus2mqtt/config/jsonarparse.py,sha256=-wcJW-O-Coqs0uqr5VVvk9mj6DWEm45NylSLkOhCECs,1084
|
|
7
|
+
dbus2mqtt/dbus/dbus_client.py,sha256=bRq9rNNWWY4uiWUYQWpgL02I9lgLGOBr5oRMR2uJHxI,44834
|
|
8
8
|
dbus2mqtt/dbus/dbus_types.py,sha256=NmPD9um499e49Pk8DWH4IrIPQh1BinHYQgoXllCNiDw,777
|
|
9
9
|
dbus2mqtt/dbus/dbus_util.py,sha256=NUe_9Aohcib_bU8RUa19UPFteDZ0_WsmgCbbnmTUvcY,5814
|
|
10
10
|
dbus2mqtt/dbus/introspection_patches/mpris_playerctl.py,sha256=q93d_Yp93u3Y-9q0dRdKW5hrij9GK3CFqKhUWVE8uw4,5883
|
|
11
11
|
dbus2mqtt/dbus/introspection_patches/mpris_vlc.py,sha256=Cf-o-05W6gUoKpcYR7n0dRi-CrbeASPTwkyEzZGnU3Y,4241
|
|
12
12
|
dbus2mqtt/flow/__init__.py,sha256=tAL-CjXQHq_tGTKctIdOZ5teVKBtcJs6Astq_RdruV8,1540
|
|
13
|
-
dbus2mqtt/flow/flow_processor.py,sha256=
|
|
13
|
+
dbus2mqtt/flow/flow_processor.py,sha256=d-M5sjuFltpR957Nsu6fCDvHKc3r5Wd_AbPvhPk4U3o,9068
|
|
14
14
|
dbus2mqtt/flow/actions/context_set.py,sha256=dIT39MJJVb0wuRI_ZM3ssnXYfa-iyB4o_UZD-1BZL2g,1087
|
|
15
15
|
dbus2mqtt/flow/actions/log_action.py,sha256=2_-YEKkX5kvFzK6x4v-Hx3u2PEM8fip_4buMg_ij-oI,1156
|
|
16
16
|
dbus2mqtt/flow/actions/mqtt_publish.py,sha256=psNkTvaR3JZwAwpM4AqiZTDnA5UQX9r4CUZ1LA7iRW4,2366
|
|
17
|
-
dbus2mqtt/mqtt/mqtt_client.py,sha256=
|
|
17
|
+
dbus2mqtt/mqtt/mqtt_client.py,sha256=bH3GV1AVC5stygOOT3ZzP4yrJa27vPIeaI7BIBg2w2Q,8078
|
|
18
18
|
dbus2mqtt/template/dbus_template_functions.py,sha256=oYXJ4HC1XCFGarf_tRzNGhvx2ECXDoT9J4Mz-cxqoJg,2447
|
|
19
|
-
dbus2mqtt/template/templating.py,sha256
|
|
20
|
-
dbus2mqtt-0.5.
|
|
21
|
-
dbus2mqtt-0.5.
|
|
22
|
-
dbus2mqtt-0.5.
|
|
23
|
-
dbus2mqtt-0.5.
|
|
24
|
-
dbus2mqtt-0.5.
|
|
19
|
+
dbus2mqtt/template/templating.py,sha256=-y_C9Gg55gK5v9mctfTSn-0N4v9e8s7HrhL8geIGVrg,5281
|
|
20
|
+
dbus2mqtt-0.5.2.dist-info/METADATA,sha256=aRN6FG81TwQl05fNPSrX7QKTSIiOT6vXZsw8ZPgEelU,5347
|
|
21
|
+
dbus2mqtt-0.5.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
22
|
+
dbus2mqtt-0.5.2.dist-info/entry_points.txt,sha256=pmmacoHCsvTTUB5dIPaY4i0H9gX7BQlpd3rBU-Jbv3A,50
|
|
23
|
+
dbus2mqtt-0.5.2.dist-info/licenses/LICENSE,sha256=a4bIEgyA9rrnAfUN90CgbgZ6BQIFHeABkk0JihiBaxM,1074
|
|
24
|
+
dbus2mqtt-0.5.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|