dbus2mqtt 0.3.1__tar.gz → 0.4.1__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.
Potentially problematic release.
This version of dbus2mqtt might be problematic. Click here for more details.
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/release-drafter.yml +2 -2
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/docker-stable.yml +2 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.pre-commit-config.yaml +3 -3
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.vscode/launch.json +8 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/PKG-INFO +18 -8
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/README.md +17 -7
- dbus2mqtt-0.4.1/docs/examples/bluez.md +37 -0
- dbus2mqtt-0.4.1/docs/examples/bluez.yaml +86 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/dbus2mqtt_internal_state.yaml +1 -1
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/home_assistant_media_player.md +9 -2
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/home_assistant_media_player.yaml +7 -3
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/linux_desktop.md +1 -1
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/linux_desktop.yaml +1 -1
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples.md +1 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/flows.md +10 -9
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/pyproject.toml +4 -2
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/config/__init__.py +24 -5
- dbus2mqtt-0.4.1/src/dbus2mqtt/dbus/dbus_client.py +820 -0
- dbus2mqtt-0.4.1/src/dbus2mqtt/dbus/dbus_types.py +37 -0
- dbus2mqtt-0.4.1/src/dbus2mqtt/dbus/dbus_util.py +24 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/event_broker.py +1 -21
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/flow/flow_processor.py +19 -5
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/main.py +17 -3
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/mqtt/mqtt_client.py +10 -3
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/template/dbus_template_functions.py +2 -2
- dbus2mqtt-0.4.1/tests/conftest.py +16 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/dbus/test_dbus_client.py +7 -5
- dbus2mqtt-0.4.1/tests/dbus/test_dbus_client_mqtt_command.py +206 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/flow/test_flow_processor.py +42 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/flow/triggers/test_dbus_client_triggers.py +86 -4
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/uv.lock +4 -4
- dbus2mqtt-0.3.1/src/dbus2mqtt/dbus/dbus_client.py +0 -476
- dbus2mqtt-0.3.1/src/dbus2mqtt/dbus/dbus_types.py +0 -23
- dbus2mqtt-0.3.1/src/dbus2mqtt/dbus/dbus_util.py +0 -23
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.dockerignore +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.env.example +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/scripts/release-versions.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/ci.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/docker-dev.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/pre-commit.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/publish.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.github/workflows/release-drafter.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.gitignore +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.python-version +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.vscode/settings.json +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/.yamllint.yml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/LICENSE +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docker/Dockerfile.dev +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docker/Dockerfile.pypi +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/debugging.md +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/docs/examples/dbus2mqtt_internal_state.md +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/renovate.json +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/__init__.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/__main__.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/config/jsonarparse.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/dbus/introspection_patches/mpris_playerctl.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/dbus/introspection_patches/mpris_vlc.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/flow/__init__.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/flow/actions/context_set.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/flow/actions/mqtt_publish.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/src/dbus2mqtt/template/templating.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/__init__.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/config/fixtures/payload_template_jinja_expressions.yaml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/config/fixtures/payload_template_off.yaml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/config/fixtures/schedule_cron_trigger.yaml +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/config/test_config.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/config/test_examples.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/flow/actions/test_context_set.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/flow/actions/test_mqtt_publish.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/template/test_templating.py +0 -0
- {dbus2mqtt-0.3.1 → dbus2mqtt-0.4.1}/tests/template/test_templating_config.py +0 -0
|
@@ -38,12 +38,12 @@ version-resolver:
|
|
|
38
38
|
minor:
|
|
39
39
|
labels:
|
|
40
40
|
- minor
|
|
41
|
-
- feature
|
|
42
|
-
- enhancement
|
|
43
41
|
- breaking-change # minor until we are on 1.x
|
|
44
42
|
patch:
|
|
45
43
|
labels:
|
|
46
44
|
- patch
|
|
45
|
+
- feature # patch until we are on 1.x
|
|
46
|
+
- enhancement # patch until we are on 1.x
|
|
47
47
|
default: patch
|
|
48
48
|
change-template: '* $TITLE (#$NUMBER)'
|
|
49
49
|
template: |
|
|
@@ -33,7 +33,7 @@ repos:
|
|
|
33
33
|
- --strict
|
|
34
34
|
|
|
35
35
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
36
|
-
rev: v0.
|
|
36
|
+
rev: v0.12.1
|
|
37
37
|
hooks:
|
|
38
38
|
- id: ruff
|
|
39
39
|
args:
|
|
@@ -42,11 +42,11 @@ repos:
|
|
|
42
42
|
- I
|
|
43
43
|
|
|
44
44
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
45
|
-
rev: 0.7.
|
|
45
|
+
rev: 0.7.16
|
|
46
46
|
hooks:
|
|
47
47
|
- id: uv-lock
|
|
48
48
|
|
|
49
49
|
- repo: https://github.com/RobertCraigie/pyright-python
|
|
50
|
-
rev: v1.1.
|
|
50
|
+
rev: v1.1.402
|
|
51
51
|
hooks:
|
|
52
52
|
- id: pyright
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
"module": "dbus2mqtt",
|
|
9
9
|
"console": "integratedTerminal",
|
|
10
10
|
"args": "--config docs/examples/home_assistant_media_player.yaml"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "dbus2mqtt - bluez",
|
|
14
|
+
"type": "debugpy",
|
|
15
|
+
"request": "launch",
|
|
16
|
+
"module": "dbus2mqtt",
|
|
17
|
+
"console": "integratedTerminal",
|
|
18
|
+
"args": "--config docs/examples/bluez.yaml"
|
|
11
19
|
}
|
|
12
20
|
]
|
|
13
21
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbus2mqtt
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: A Python tool to expose Linux D-Bus signals, methods and properties over MQTT - featuring templating, payload enrichment and Home Assistant-ready examples
|
|
5
5
|
Project-URL: Repository, https://github.com/jwnmulder/dbus2mqtt.git
|
|
6
6
|
Project-URL: Issues, https://github.com/jwnmulder/dbus2mqtt/issues
|
|
@@ -53,7 +53,7 @@ Initial testing has focused on MPRIS integration. A table of tested MPRIS player
|
|
|
53
53
|
|
|
54
54
|
## Getting started with dbus2mqtt
|
|
55
55
|
|
|
56
|
-
Create a `config.yaml` file with the contents shown below. This configuration will expose all bus properties from the `org.mpris.MediaPlayer2.Player` interface to MQTT on the `dbus2mqtt/org.mpris.MediaPlayer2/state` topic. Have a look at [docs/examples](docs/examples.md) for more examples
|
|
56
|
+
Create a `config.yaml` file with the contents shown below. This configuration will expose all bus properties from the `org.mpris.MediaPlayer2.Player` interface to MQTT on the `dbus2mqtt/org.mpris.MediaPlayer2/state` topic. Have a look at [docs/examples](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples.md) for more examples
|
|
57
57
|
|
|
58
58
|
```yaml
|
|
59
59
|
dbus:
|
|
@@ -68,7 +68,7 @@ dbus:
|
|
|
68
68
|
flows:
|
|
69
69
|
- name: "Publish MPRIS state"
|
|
70
70
|
triggers:
|
|
71
|
-
- type:
|
|
71
|
+
- type: object_added
|
|
72
72
|
- type: schedule
|
|
73
73
|
interval: {seconds: 5}
|
|
74
74
|
actions:
|
|
@@ -111,8 +111,8 @@ cp docs/examples/home_assistant_media_player.yaml $HOME/.config/dbus2mqtt/config
|
|
|
111
111
|
cp .env.example $HOME/.config/dbus2mqtt/.env
|
|
112
112
|
|
|
113
113
|
# run image and automatically start on reboot
|
|
114
|
-
docker pull jwnmulder/dbus2mqtt
|
|
115
|
-
docker run --detach --name dbus2mqtt \
|
|
114
|
+
sudo docker pull jwnmulder/dbus2mqtt
|
|
115
|
+
sudo docker run --detach --name dbus2mqtt \
|
|
116
116
|
--volume "$HOME"/.config/dbus2mqtt:"$HOME"/.config/dbus2mqtt \
|
|
117
117
|
--volume /run/user:/run/user \
|
|
118
118
|
--env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
|
|
@@ -173,21 +173,31 @@ dbus:
|
|
|
173
173
|
|
|
174
174
|
This configuration will expose 2 methods. Triggering methods can be done by publishing json messages to the `dbus2mqtt/org.mpris.MediaPlayer2/command` MQTT topic. Arguments can be passed along in `args`.
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
Some examples that call methods on **all** bus_names matching the configured pattern
|
|
177
177
|
|
|
178
178
|
```json
|
|
179
179
|
{
|
|
180
|
-
"method"
|
|
180
|
+
"method": "Play",
|
|
181
181
|
}
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
```json
|
|
185
185
|
{
|
|
186
|
-
"method"
|
|
186
|
+
"method": "OpenUri",
|
|
187
187
|
"args": []
|
|
188
188
|
}
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
+
To specifically target objects the properties `bus_name` and/or `path` can be used. Both properties support wildcards
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"method": "Play",
|
|
196
|
+
"bus_name": "*.firefox",
|
|
197
|
+
"path": "/org/mpris/MediaPlayer2"
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
191
201
|
### Exposing dbus signals
|
|
192
202
|
|
|
193
203
|
Publishing signals to MQTT topics works by subscribing to the relevant signal and using flows for publishing
|
|
@@ -21,7 +21,7 @@ Initial testing has focused on MPRIS integration. A table of tested MPRIS player
|
|
|
21
21
|
|
|
22
22
|
## Getting started with dbus2mqtt
|
|
23
23
|
|
|
24
|
-
Create a `config.yaml` file with the contents shown below. This configuration will expose all bus properties from the `org.mpris.MediaPlayer2.Player` interface to MQTT on the `dbus2mqtt/org.mpris.MediaPlayer2/state` topic. Have a look at [docs/examples](docs/examples.md) for more examples
|
|
24
|
+
Create a `config.yaml` file with the contents shown below. This configuration will expose all bus properties from the `org.mpris.MediaPlayer2.Player` interface to MQTT on the `dbus2mqtt/org.mpris.MediaPlayer2/state` topic. Have a look at [docs/examples](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples.md) for more examples
|
|
25
25
|
|
|
26
26
|
```yaml
|
|
27
27
|
dbus:
|
|
@@ -36,7 +36,7 @@ dbus:
|
|
|
36
36
|
flows:
|
|
37
37
|
- name: "Publish MPRIS state"
|
|
38
38
|
triggers:
|
|
39
|
-
- type:
|
|
39
|
+
- type: object_added
|
|
40
40
|
- type: schedule
|
|
41
41
|
interval: {seconds: 5}
|
|
42
42
|
actions:
|
|
@@ -79,8 +79,8 @@ cp docs/examples/home_assistant_media_player.yaml $HOME/.config/dbus2mqtt/config
|
|
|
79
79
|
cp .env.example $HOME/.config/dbus2mqtt/.env
|
|
80
80
|
|
|
81
81
|
# run image and automatically start on reboot
|
|
82
|
-
docker pull jwnmulder/dbus2mqtt
|
|
83
|
-
docker run --detach --name dbus2mqtt \
|
|
82
|
+
sudo docker pull jwnmulder/dbus2mqtt
|
|
83
|
+
sudo docker run --detach --name dbus2mqtt \
|
|
84
84
|
--volume "$HOME"/.config/dbus2mqtt:"$HOME"/.config/dbus2mqtt \
|
|
85
85
|
--volume /run/user:/run/user \
|
|
86
86
|
--env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
|
|
@@ -141,21 +141,31 @@ dbus:
|
|
|
141
141
|
|
|
142
142
|
This configuration will expose 2 methods. Triggering methods can be done by publishing json messages to the `dbus2mqtt/org.mpris.MediaPlayer2/command` MQTT topic. Arguments can be passed along in `args`.
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
Some examples that call methods on **all** bus_names matching the configured pattern
|
|
145
145
|
|
|
146
146
|
```json
|
|
147
147
|
{
|
|
148
|
-
"method"
|
|
148
|
+
"method": "Play",
|
|
149
149
|
}
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
```json
|
|
153
153
|
{
|
|
154
|
-
"method"
|
|
154
|
+
"method": "OpenUri",
|
|
155
155
|
"args": []
|
|
156
156
|
}
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
To specifically target objects the properties `bus_name` and/or `path` can be used. Both properties support wildcards
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"method": "Play",
|
|
164
|
+
"bus_name": "*.firefox",
|
|
165
|
+
"path": "/org/mpris/MediaPlayer2"
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
159
169
|
### Exposing dbus signals
|
|
160
170
|
|
|
161
171
|
Publishing signals to MQTT topics works by subscribing to the relevant signal and using flows for publishing
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Bluez
|
|
2
|
+
|
|
3
|
+
This configuration file demonstrates how to use dbus2mqtt to bridge D-Bus events from BlueZ (the official Linux Bluetooth protocol stack) to MQTT topics. It subscribes to relevant D-Bus signals and properties for both the Bluetooth adapter (`hci0`) and all Bluetooth devices managed by BlueZ. The configuration defines flows that:
|
|
4
|
+
|
|
5
|
+
* Monitor property changes and object lifecycle events (added/removed) for the Bluetooth adapter and devices.
|
|
6
|
+
* Retrieve the current state of the adapter or device using the `GetAll` method from the `org.freedesktop.DBus.Properties` interface.
|
|
7
|
+
* Publish the retrieved state as JSON payloads to structured MQTT topics, enabling real-time monitoring and integration with home automation or IoT systems.
|
|
8
|
+
|
|
9
|
+
This setup allows MQTT clients to receive updates about Bluetooth adapter and device states, as well as notifications when devices are removed, making it easier to integrate Bluetooth events into broader automation workflows.
|
|
10
|
+
|
|
11
|
+
Configuration activities
|
|
12
|
+
|
|
13
|
+
* dbus2mqtt setup using the supplied [bluez.yaml](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/bluez.yaml)
|
|
14
|
+
|
|
15
|
+
Execute the following command to run dbus2mqtt with the example configuration in this repository.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv run dbus2mqtt --config docs/examples/bluez.yaml
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
The following table lists commands, their descriptions, and an example JSON payload for invoking them via MQTT.
|
|
24
|
+
|
|
25
|
+
Dbus methods can be invoked by sendig the JSON payload to MQTT topic `dbus2mqtt/bluez/hci0/command`. Method calls will be done for all matching dbus objects.
|
|
26
|
+
|
|
27
|
+
| Interface | Method<br />Property | Description | Example MQTT JSON Payload |
|
|
28
|
+
|----------------------|-----------------------|--------------------------------------|-------------------------------------------------|
|
|
29
|
+
| `org.bluez.Adapter1` | `StartDiscovery` | Starts bluetooth discovery | `{ "method": "StartDiscovery" }` |
|
|
30
|
+
| `org.bluez.Adapter1` | `StopDiscovery` | Stops bluetooth discovery | `{ "method": "StopDiscovery" }` |
|
|
31
|
+
| `org.bluez.Device1` | `Connect` | | `{ "method": "Connect", "path": "/org/bluez/hci0/dev_A1_A2_A3_A4_A5_A6" }` |
|
|
32
|
+
| `org.bluez.Device1` | `Disconnect` | | `{ "method": "Disconnect", "path": "/org/bluez/hci0/dev_A1_A2_A3_A4_A5_A6" }` |
|
|
33
|
+
| `org.bluez.Device1` | `Pair` | | `{ "method": "Pair", "path": "/org/bluez/hci0/dev_A1_A2_A3_A4_A5_A6" }` |
|
|
34
|
+
| `org.bluez.Device1` | `CancelPairing` | | `{ "method": "CancelPairing", "path": "/org/bluez/hci0/dev_A1_A2_A3_A4_A5_A6" }` |
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
https://manpages.ubuntu.com/manpages/noble/man5/org.bluez.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
dbus:
|
|
2
|
+
bus_type: SYSTEM
|
|
3
|
+
subscriptions:
|
|
4
|
+
|
|
5
|
+
- bus_name: org.bluez
|
|
6
|
+
path: /org/bluez/hci0
|
|
7
|
+
|
|
8
|
+
# https://manpages.ubuntu.com/manpages/oracular/man5/org.bluez.Adapter.5.html
|
|
9
|
+
|
|
10
|
+
interfaces:
|
|
11
|
+
- interface: org.freedesktop.DBus.Properties
|
|
12
|
+
signals:
|
|
13
|
+
- signal: PropertiesChanged
|
|
14
|
+
|
|
15
|
+
- interface: org.bluez.Adapter1
|
|
16
|
+
mqtt_command_topic: dbus2mqtt/bluez/hci0/command
|
|
17
|
+
methods:
|
|
18
|
+
- method: StartDiscovery
|
|
19
|
+
- method: StopDiscovery
|
|
20
|
+
|
|
21
|
+
flows:
|
|
22
|
+
- name: "publish adapter state"
|
|
23
|
+
triggers:
|
|
24
|
+
- type: object_added
|
|
25
|
+
- type: dbus_signal
|
|
26
|
+
interface: org.freedesktop.DBus.Properties
|
|
27
|
+
signal: PropertiesChanged
|
|
28
|
+
actions:
|
|
29
|
+
- type: context_set
|
|
30
|
+
context:
|
|
31
|
+
adapter_properties: |
|
|
32
|
+
{{ dbus_call('org.bluez', '/org/bluez/hci0', 'org.freedesktop.DBus.Properties', 'GetAll', ['org.bluez.Adapter1']) }}
|
|
33
|
+
- type: mqtt_publish
|
|
34
|
+
topic: dbus2mqtt/bluez/hci0
|
|
35
|
+
payload_type: json
|
|
36
|
+
payload_template: |
|
|
37
|
+
{{
|
|
38
|
+
{ 'dbus_object_path': path }
|
|
39
|
+
| combine(adapter_properties)
|
|
40
|
+
}}
|
|
41
|
+
|
|
42
|
+
- bus_name: org.bluez
|
|
43
|
+
path: /org/bluez/hci0/dev_*
|
|
44
|
+
|
|
45
|
+
# https://manpages.ubuntu.com/manpages/noble/man5/org.bluez.Device.5.html
|
|
46
|
+
interfaces:
|
|
47
|
+
- interface: org.freedesktop.DBus.Properties
|
|
48
|
+
signals:
|
|
49
|
+
- signal: PropertiesChanged
|
|
50
|
+
|
|
51
|
+
- interface: org.bluez.Device1
|
|
52
|
+
mqtt_command_topic: dbus2mqtt/bluez/hci0/command
|
|
53
|
+
methods:
|
|
54
|
+
- method: Connect
|
|
55
|
+
- method: Disconnect
|
|
56
|
+
- method: Pair
|
|
57
|
+
- method: CancelPairing
|
|
58
|
+
|
|
59
|
+
flows:
|
|
60
|
+
- name: "publish device state"
|
|
61
|
+
triggers:
|
|
62
|
+
- type: object_added
|
|
63
|
+
- type: dbus_signal
|
|
64
|
+
interface: org.freedesktop.DBus.Properties
|
|
65
|
+
signal: PropertiesChanged
|
|
66
|
+
actions:
|
|
67
|
+
- type: context_set
|
|
68
|
+
context:
|
|
69
|
+
device_properties: |
|
|
70
|
+
{{ dbus_call('org.bluez', path, 'org.freedesktop.DBus.Properties', 'GetAll', ['org.bluez.Device1']) }}
|
|
71
|
+
- type: mqtt_publish
|
|
72
|
+
topic: dbus2mqtt/bluez/{{ path | replace('/org/bluez/', '') }}
|
|
73
|
+
payload_type: json
|
|
74
|
+
payload_template: |
|
|
75
|
+
{{
|
|
76
|
+
{ 'dbus_object_path': path }
|
|
77
|
+
| combine(device_properties)
|
|
78
|
+
}}
|
|
79
|
+
- name: "device removed"
|
|
80
|
+
triggers:
|
|
81
|
+
- type: object_removed
|
|
82
|
+
actions:
|
|
83
|
+
- type: mqtt_publish
|
|
84
|
+
topic: dbus2mqtt/bluez/{{ path | replace('/org/bluez/', '') }}
|
|
85
|
+
payload_type: json
|
|
86
|
+
payload_template: "{{ None }}"
|
|
@@ -19,7 +19,7 @@ Features:
|
|
|
19
19
|
Configuration activities
|
|
20
20
|
|
|
21
21
|
* MQTT Sensor and player configuration in Home Assistant (see below)
|
|
22
|
-
* dbus2mqtt setup using the supplied
|
|
22
|
+
* dbus2mqtt setup using the supplied [home_assistant_media_player.yaml](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.yaml)
|
|
23
23
|
|
|
24
24
|
Execute the following command to run dbus2mqtt with the example configuration in this repository.
|
|
25
25
|
|
|
@@ -36,6 +36,8 @@ The following setup is known to work with Home Assistant.
|
|
|
36
36
|
| `Firefox` | ✅ | ✅ | ✅ | ✅ | | ❌ | ✅ | ✅ | |
|
|
37
37
|
| `VLC` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | |
|
|
38
38
|
| `Chromium` | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✔️ | Images not working when Chromium is running as snap |
|
|
39
|
+
| `Kodi` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | Requires Kodi plugin [MediaPlayerRemoteInterface](https://github.com/wastis/MediaPlayerRemoteInterface)<br /> Requires path to be set to '/'<br />Signals not working due to non-defaut path |
|
|
40
|
+
|
|
39
41
|
|
|
40
42
|
More players that support MPRIS can be found here: <https://wiki.archlinux.org/title/MPRIS>
|
|
41
43
|
|
|
@@ -97,7 +99,12 @@ media_player:
|
|
|
97
99
|
media_content_type_template: music # needed to show 'artist'
|
|
98
100
|
media_duration_template: "{{ (state_attr('sensor.mpris_media_player', 'Metadata') or {}).get('mpris:length', 0) }}"
|
|
99
101
|
album_template: "{{ (state_attr('sensor.mpris_media_player', 'Metadata') or {}).get('xesam:album', '') }}"
|
|
100
|
-
artist_template:
|
|
102
|
+
artist_template: >-
|
|
103
|
+
{% set artist = (state_attr('sensor.mpris_media_player', 'Metadata') or {}).get('xesam:artist', '') %}
|
|
104
|
+
{% if artist is string %}
|
|
105
|
+
{% set artist = [artist] %}
|
|
106
|
+
{% endif %}
|
|
107
|
+
{{ artist | first }}
|
|
101
108
|
|
|
102
109
|
# mpris:artUrl might contain a file:// schema. In these cases we rely on images published via MQTT
|
|
103
110
|
media_image_url_template: >-
|
|
@@ -42,7 +42,7 @@ dbus:
|
|
|
42
42
|
flows:
|
|
43
43
|
- name: "publish player state"
|
|
44
44
|
triggers:
|
|
45
|
-
- type:
|
|
45
|
+
- type: object_added
|
|
46
46
|
- type: schedule
|
|
47
47
|
interval: {seconds: 5}
|
|
48
48
|
- type: dbus_signal
|
|
@@ -57,6 +57,9 @@ dbus:
|
|
|
57
57
|
context:
|
|
58
58
|
mpris_bus_name: '{{ dbus_list("org.mpris.MediaPlayer2.*") | first }}'
|
|
59
59
|
mpris_path: /org/mpris/MediaPlayer2
|
|
60
|
+
# Some players return stale position if GetAll is executed immediately after a seeked signal.
|
|
61
|
+
# By storing the seeked position it can be used to override Position below
|
|
62
|
+
seeked_position: '{{ args[0] if trigger_type == "dbus_signal" and signal == "Seeked" else None }}'
|
|
60
63
|
- type: context_set
|
|
61
64
|
context:
|
|
62
65
|
player_properties: |
|
|
@@ -68,13 +71,14 @@ dbus:
|
|
|
68
71
|
{{
|
|
69
72
|
{ 'bus_name': mpris_bus_name }
|
|
70
73
|
| combine(player_properties)
|
|
74
|
+
| combine ({ 'Position': seeked_position } if seeked_position else {})
|
|
71
75
|
}}
|
|
72
76
|
|
|
73
77
|
- name: "publish local art image"
|
|
74
78
|
# mpris:artUrl can have a file:// or http:// schema
|
|
75
79
|
# Home Assistant is unable to access file:// so we use MQTT for that
|
|
76
80
|
triggers:
|
|
77
|
-
- type:
|
|
81
|
+
- type: object_added
|
|
78
82
|
- type: dbus_signal
|
|
79
83
|
interface: org.freedesktop.DBus.Properties
|
|
80
84
|
signal: PropertiesChanged
|
|
@@ -90,7 +94,7 @@ dbus:
|
|
|
90
94
|
|
|
91
95
|
- name: "player removed"
|
|
92
96
|
triggers:
|
|
93
|
-
- type:
|
|
97
|
+
- type: object_removed
|
|
94
98
|
# filter: # TODO: Check if this is the last or inactive one #
|
|
95
99
|
actions:
|
|
96
100
|
- type: mqtt_publish
|
|
@@ -6,8 +6,8 @@ Flows can be defined on a global or dbus subscription level and can be triggered
|
|
|
6
6
|
|
|
7
7
|
* `schedule` for cron based schedules
|
|
8
8
|
* `dbus_signal` for when dbus signal occur
|
|
9
|
-
* `
|
|
10
|
-
* `
|
|
9
|
+
* `object_added` when a new bus_name is registered on dbus
|
|
10
|
+
* `object_removed` when a bus_name is removed from dbus
|
|
11
11
|
|
|
12
12
|
Within each flow a set of actions can be configured. These are executed in order
|
|
13
13
|
|
|
@@ -53,14 +53,15 @@ When triggered, the following context parameters are available
|
|
|
53
53
|
| name | type | description |
|
|
54
54
|
|------|------|-------------|
|
|
55
55
|
| bus_name | string | bus_name of the object that was registered on dbus |
|
|
56
|
-
| path | string |
|
|
56
|
+
| path | string | path of the object that was registered on dbus |
|
|
57
57
|
| interface | string | name of interface for which the signal was triggered |
|
|
58
|
+
| signal | string | name of the signal, e.g. 'Seeked'
|
|
58
59
|
| args | list | signal arguments, list of objects |
|
|
59
60
|
|
|
60
|
-
###
|
|
61
|
+
### object_added
|
|
61
62
|
|
|
62
63
|
```yaml
|
|
63
|
-
type:
|
|
64
|
+
type: object_added
|
|
64
65
|
```
|
|
65
66
|
|
|
66
67
|
When triggered, the following context parameters are available
|
|
@@ -68,12 +69,12 @@ When triggered, the following context parameters are available
|
|
|
68
69
|
| name | description |
|
|
69
70
|
|------|-------------|
|
|
70
71
|
| bus_name | bus_name of the object that was registered on dbus |
|
|
71
|
-
| path |
|
|
72
|
+
| path | path of the object that was registered on dbus |
|
|
72
73
|
|
|
73
|
-
###
|
|
74
|
+
### object_removed
|
|
74
75
|
|
|
75
76
|
```yaml
|
|
76
|
-
type:
|
|
77
|
+
type: object_removed
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
When triggered, the following context parameters are available
|
|
@@ -81,7 +82,7 @@ When triggered, the following context parameters are available
|
|
|
81
82
|
| name | description |
|
|
82
83
|
|------|-------------|
|
|
83
84
|
| bus_name | bus_name of the object that was registered on dbus |
|
|
84
|
-
| path |
|
|
85
|
+
| path | path of the object that was registered on dbus |
|
|
85
86
|
|
|
86
87
|
## Flow actions
|
|
87
88
|
|
|
@@ -60,7 +60,7 @@ dev = [
|
|
|
60
60
|
"pyright>=1.1.396",
|
|
61
61
|
"pre-commit>=4.2.0",
|
|
62
62
|
"pip>=25.0.1",
|
|
63
|
-
"pytest-asyncio>=0.
|
|
63
|
+
"pytest-asyncio>=1.0.0"
|
|
64
64
|
]
|
|
65
65
|
|
|
66
66
|
[project.urls]
|
|
@@ -81,7 +81,9 @@ lint-pyright = "pyright"
|
|
|
81
81
|
addopts = "-s"
|
|
82
82
|
testpaths = ["tests"]
|
|
83
83
|
pythonpath = "."
|
|
84
|
-
asyncio_default_fixture_loop_scope = "
|
|
84
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
85
|
+
asyncio_default_test_loop_scope = "function"
|
|
86
|
+
log_cli = true
|
|
85
87
|
|
|
86
88
|
[tool.pyright]
|
|
87
89
|
venvPath = "."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fnmatch
|
|
2
2
|
import uuid
|
|
3
|
+
import warnings
|
|
3
4
|
|
|
4
5
|
from dataclasses import dataclass, field
|
|
5
6
|
from typing import Annotated, Any, Literal
|
|
@@ -65,15 +66,29 @@ class FlowTriggerDbusSignalConfig:
|
|
|
65
66
|
@dataclass
|
|
66
67
|
class FlowTriggerBusNameAddedConfig:
|
|
67
68
|
type: Literal["bus_name_added"] = "bus_name_added"
|
|
68
|
-
|
|
69
|
+
|
|
70
|
+
def __post_init__(self):
|
|
71
|
+
warnings.warn(f"{self.type} flow trigger may be removed in a future version.", DeprecationWarning, stacklevel=2)
|
|
69
72
|
|
|
70
73
|
@dataclass
|
|
71
74
|
class FlowTriggerBusNameRemovedConfig:
|
|
72
75
|
type: Literal["bus_name_removed"] = "bus_name_removed"
|
|
76
|
+
|
|
77
|
+
def __post_init__(self):
|
|
78
|
+
warnings.warn(f"{self.type} flow trigger may be removed in a future version.", DeprecationWarning, stacklevel=2)
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class FlowTriggerObjectAddedConfig:
|
|
82
|
+
type: Literal["object_added"] = "object_added"
|
|
83
|
+
# filter: str | None = None
|
|
84
|
+
|
|
85
|
+
@dataclass
|
|
86
|
+
class FlowTriggerObjectRemovedConfig:
|
|
87
|
+
type: Literal["object_removed"] = "object_removed"
|
|
73
88
|
# filter: str | None = None
|
|
74
89
|
|
|
75
90
|
FlowTriggerConfig = Annotated[
|
|
76
|
-
FlowTriggerMqttConfig | FlowTriggerScheduleConfig | FlowTriggerDbusSignalConfig | FlowTriggerBusNameAddedConfig | FlowTriggerBusNameRemovedConfig,
|
|
91
|
+
FlowTriggerMqttConfig | FlowTriggerScheduleConfig | FlowTriggerDbusSignalConfig | FlowTriggerBusNameAddedConfig | FlowTriggerBusNameRemovedConfig | FlowTriggerObjectAddedConfig | FlowTriggerObjectRemovedConfig,
|
|
77
92
|
Field(discriminator="type")
|
|
78
93
|
]
|
|
79
94
|
|
|
@@ -117,6 +132,7 @@ class SubscriptionConfig:
|
|
|
117
132
|
@dataclass
|
|
118
133
|
class DbusConfig:
|
|
119
134
|
subscriptions: list[SubscriptionConfig]
|
|
135
|
+
bus_type: Literal["SESSION", "SYSTEM"] = "SESSION"
|
|
120
136
|
|
|
121
137
|
def is_bus_name_configured(self, bus_name: str) -> bool:
|
|
122
138
|
|
|
@@ -125,11 +141,14 @@ class DbusConfig:
|
|
|
125
141
|
return True
|
|
126
142
|
return False
|
|
127
143
|
|
|
128
|
-
def get_subscription_configs(self, bus_name: str, path: str) -> list[SubscriptionConfig]:
|
|
144
|
+
def get_subscription_configs(self, bus_name: str, path: str|None = None) -> list[SubscriptionConfig]:
|
|
129
145
|
res: list[SubscriptionConfig] = []
|
|
130
146
|
for subscription in self.subscriptions:
|
|
131
|
-
if fnmatch.fnmatchcase(bus_name, subscription.bus_name)
|
|
132
|
-
|
|
147
|
+
if fnmatch.fnmatchcase(bus_name, subscription.bus_name):
|
|
148
|
+
if not path or path == subscription.path:
|
|
149
|
+
res.append(subscription)
|
|
150
|
+
elif fnmatch.fnmatchcase(path, subscription.path):
|
|
151
|
+
res.append(subscription)
|
|
133
152
|
return res
|
|
134
153
|
|
|
135
154
|
@dataclass
|