dbus2mqtt 0.1.1__tar.gz → 0.1.2__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.

Files changed (57) hide show
  1. dbus2mqtt-0.1.2/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  2. dbus2mqtt-0.1.2/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  3. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.github/release-drafter.yml +1 -2
  4. dbus2mqtt-0.1.1/.github/workflows/main.yml → dbus2mqtt-0.1.2/.github/workflows/ci.yml +1 -1
  5. dbus2mqtt-0.1.2/.github/workflows/docker-latest.yml +74 -0
  6. dbus2mqtt-0.1.2/.github/workflows/docker-publish-pypi-release.yml +69 -0
  7. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.github/workflows/publish.yml +0 -8
  8. dbus2mqtt-0.1.2/.gitignore +25 -0
  9. dbus2mqtt-0.1.2/.python-version +1 -0
  10. dbus2mqtt-0.1.2/.vscode/launch.json +13 -0
  11. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/PKG-INFO +17 -16
  12. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/README.md +15 -15
  13. dbus2mqtt-0.1.1/Dockerfile → dbus2mqtt-0.1.2/docker/Dockerfile.latest +5 -3
  14. dbus2mqtt-0.1.2/docker/Dockerfile.pypi +10 -0
  15. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/examples/home_assistant_media_player.md +51 -25
  16. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/examples/home_assistant_media_player.yaml +10 -7
  17. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/pyproject.toml +1 -0
  18. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/config.py +1 -1
  19. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/dbus/dbus_client.py +11 -9
  20. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/dbus/dbus_util.py +1 -1
  21. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/event_broker.py +1 -2
  22. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/__init__.py +18 -1
  23. dbus2mqtt-0.1.2/tests/dbus/test_dbus_client.py +49 -0
  24. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/flow/triggers/test_dbus_client_triggers.py +6 -25
  25. dbus2mqtt-0.1.1/.gitignore +0 -6
  26. dbus2mqtt-0.1.1/.python-version +0 -1
  27. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.dockerignore +0 -0
  28. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.env.example +0 -0
  29. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.github/workflows/pre-commit.yml +0 -0
  30. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.github/workflows/release-drafter.yml +0 -0
  31. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.pre-commit-config.yaml +0 -0
  32. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.vscode/settings.json +0 -0
  33. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/.yamllint.yml +0 -0
  34. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/LICENSE +0 -0
  35. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/config-test.yaml +0 -0
  36. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/debugging.md +0 -0
  37. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/examples/linux_desktop.md +0 -0
  38. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/examples/linux_desktop.yaml +0 -0
  39. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/docs/examples.md +0 -0
  40. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/renovate.json +0 -0
  41. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/__init__.py +0 -0
  42. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/__main__.py +0 -0
  43. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/dbus/dbus_types.py +0 -0
  44. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/flow/__init__.py +0 -0
  45. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/flow/actions/context_set.py +0 -0
  46. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/flow/actions/mqtt_publish.py +0 -0
  47. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/flow/flow_processor.py +0 -0
  48. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/main.py +0 -0
  49. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/mqtt/mqtt_client.py +0 -0
  50. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/template/dbus_template_functions.py +0 -0
  51. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/src/dbus2mqtt/template/templating.py +0 -0
  52. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/config/test_examples.py +0 -0
  53. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/flow/actions/test_context_set.py +0 -0
  54. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/flow/actions/test_mqtt_publish.py +0 -0
  55. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/flow/test_flow_processor.py +0 -0
  56. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/tests/template/test_templating.py +0 -0
  57. {dbus2mqtt-0.1.1 → dbus2mqtt-0.1.2}/uv.lock +0 -0
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Desktop (please complete the following information):**
27
+ - OS: [e.g. iOS]
28
+ - Browser [e.g. chrome, safari]
29
+ - Version [e.g. 22]
30
+
31
+ **Smartphone (please complete the following information):**
32
+ - Device: [e.g. iPhone6]
33
+ - OS: [e.g. iOS8.1]
34
+ - Browser [e.g. stock browser, safari]
35
+ - Version [e.g. 22]
36
+
37
+ **Additional context**
38
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -14,8 +14,6 @@ categories:
14
14
  - 'bug'
15
15
  - title: '🧰 Maintenance'
16
16
  label: 'chore'
17
- # change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
18
- # change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
19
17
  exclude-contributors:
20
18
  - jwnmulder
21
19
  version-resolver:
@@ -29,6 +27,7 @@ version-resolver:
29
27
  labels:
30
28
  - 'patch'
31
29
  default: patch
30
+ change-template: '* $TITLE (#$NUMBER)'
32
31
  template: |
33
32
  ## Changes
34
33
 
@@ -1,4 +1,4 @@
1
- name: main
1
+ name: CI
2
2
 
3
3
  "on":
4
4
  push:
@@ -0,0 +1,74 @@
1
+ name: Build and Push Docker latest
2
+
3
+ "on":
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ docker:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ packages: write
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v5
20
+ with:
21
+ enable-cache: true
22
+
23
+ - name: "Set up Python"
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version-file: ".python-version"
27
+
28
+ - name: Determine version from hatch
29
+ id: version
30
+ run: echo "PRETEND_VERSION=$(uvx hatch version)" >> "$GITHUB_OUTPUT"
31
+
32
+ - name: Docker meta
33
+ id: meta
34
+ uses: docker/metadata-action@v5
35
+ with:
36
+ images: |
37
+ jwnmulder/dbus2mqtt
38
+ ghcr.io/jwnmulder/dbus2mqtt
39
+ tags: |
40
+ type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
41
+ labels: |
42
+ org.opencontainers.image.source=https://github.com/jwnmulder/dbus2mqtt
43
+
44
+ - name: Set up QEMU
45
+ uses: docker/setup-qemu-action@v3
46
+
47
+ - name: Set up Docker Buildx
48
+ uses: docker/setup-buildx-action@v3
49
+
50
+ - name: Login to DockerHub
51
+ if: github.event_name != 'pull_request'
52
+ uses: docker/login-action@v3
53
+ with:
54
+ username: jwnmulder
55
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
56
+
57
+ - name: Login to GHCR
58
+ if: github.event_name != 'pull_request'
59
+ uses: docker/login-action@v3
60
+ with:
61
+ registry: ghcr.io
62
+ username: jwnmulder
63
+ password: ${{ secrets.GITHUB_TOKEN }}
64
+
65
+ - name: Build and push
66
+ uses: docker/build-push-action@v6
67
+ with:
68
+ context: .
69
+ file: ./docker/Dockerfile.latest
70
+ push: ${{ github.event_name != 'pull_request' }}
71
+ tags: ${{ steps.meta.outputs.tags }}
72
+ labels: ${{ steps.meta.outputs.labels }}
73
+ build-args: |
74
+ PRETEND_VERSION=${{ steps.version.outputs.PRETEND_VERSION }}
@@ -0,0 +1,69 @@
1
+ name: Build and Push Docker Images for Released Versions
2
+
3
+ "on":
4
+ # push:
5
+ # branches:
6
+ # - main
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ docker:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ packages: write
14
+ strategy:
15
+ matrix:
16
+ version:
17
+ - 0.1
18
+
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Docker meta
24
+ id: meta
25
+ uses: docker/metadata-action@v5
26
+ with:
27
+ images: |
28
+ jwnmulder/dbus2mqtt
29
+ ghcr.io/jwnmulder/dbus2mqtt
30
+ tags: |
31
+ type=pep440,pattern={{major}},value=${{ matrix.version }},enable=${{ !startsWith(matrix.version, '0.') }}
32
+ type=pep440,pattern={{major}}.{{minor}},value=${{ matrix.version }}
33
+ # type=ref,event=branch
34
+ # type=ref,event=pr
35
+ # type=semver,pattern={{version}},value=${{ matrix.version }}
36
+ labels: |
37
+ org.opencontainers.image.source=https://github.com/jwnmulder/dbus2mqtt
38
+
39
+ - name: Set up QEMU
40
+ uses: docker/setup-qemu-action@v3
41
+
42
+ - name: Set up Docker Buildx
43
+ uses: docker/setup-buildx-action@v3
44
+
45
+ - name: Login to DockerHub
46
+ if: github.event_name != 'pull_request'
47
+ uses: docker/login-action@v3
48
+ with:
49
+ username: jwnmulder
50
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
51
+
52
+ - name: Login to GHCR
53
+ if: github.event_name != 'pull_request'
54
+ uses: docker/login-action@v3
55
+ with:
56
+ registry: ghcr.io
57
+ username: jwnmulder
58
+ password: ${{ secrets.GITHUB_TOKEN }}
59
+
60
+ - name: Build and push
61
+ uses: docker/build-push-action@v6
62
+ with:
63
+ context: .
64
+ file: ./docker/Dockerfile.pypi
65
+ push: ${{ github.event_name != 'pull_request' }}
66
+ tags: ${{ steps.meta.outputs.tags }}
67
+ labels: ${{ steps.meta.outputs.labels }}
68
+ build-args: |
69
+ DBUS2MQTT_VERSION=${{ matrix.version }}
@@ -1,11 +1,3 @@
1
- # This workflow will upload a Python Package to PyPI when a release is created
2
- # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
-
4
- # This workflow uses actions that are not certified by GitHub.
5
- # They are provided by a third-party and are governed by
6
- # separate terms of service, privacy policy, and support
7
- # documentation.
8
-
9
1
  name: Upload Python Package
10
2
 
11
3
  "on":
@@ -0,0 +1,25 @@
1
+ # https://github.com/github/gitignore/blob/main/Python.gitignore
2
+ # https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # Distribution / packaging
10
+ dist/
11
+
12
+ # Environments
13
+ .env
14
+ .venv
15
+
16
+ # Ruff stuff:
17
+ .ruff_cache/
18
+
19
+ ### VisualStudioCode ###
20
+ .vscode/*
21
+ !.vscode/settings.json
22
+ !.vscode/tasks.json
23
+ !.vscode/launch.json
24
+ !.vscode/extensions.json
25
+ *.code-workspace
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "dbus2mqtt - home_assistant_media_player",
6
+ "type": "debugpy",
7
+ "request": "launch",
8
+ "module": "dbus2mqtt",
9
+ "console": "integratedTerminal",
10
+ "args": "--config docs/examples/home_assistant_media_player.yaml"
11
+ }
12
+ ]
13
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbus2mqtt
3
- Version: 0.1.1
3
+ Version: 0.1.2
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
@@ -9,6 +9,7 @@ License-File: LICENSE
9
9
  Keywords: dbus,home-assistant,mpris,mqtt,python
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
12
13
  Classifier: Operating System :: POSIX :: Linux
13
14
  Classifier: Programming Language :: Python :: 3
14
15
  Classifier: Programming Language :: Python :: 3.10
@@ -31,8 +32,6 @@ Description-Content-Type: text/markdown
31
32
 
32
33
  # dbus2mqtt
33
34
 
34
- > **⚠️ Warning:** This project has no releases yet. Running from source works. Docker images and Python packages are planned but not yet available.
35
-
36
35
  **dbus2mqtt** is a Python application that bridges **Linux D-Bus** with **MQTT**.
37
36
  It lets you forward D-Bus signals and properties to MQTT topics, call D-Bus methods via MQTT messages, and shape payloads using flexible **Jinja2 templating**.
38
37
 
@@ -46,10 +45,15 @@ This makes it easy to integrate Linux desktop services or system signals into MQ
46
45
  * 📡 Expose **D-Bus methods** for remote control via MQTT messages.
47
46
  * 🏠 Includes example configurations for **MPRIS** and **Home Assistant Media Player** integration.
48
47
 
48
+ ## Project status
49
+
50
+ **dbus2mqtt** is considered stable for the use-cases it has been tested against, and is actively being developed. Documentation is continuously being improved.
51
+
52
+ Initial testing has focused on MPRIS integration. A table of tested MPRIS players and their supported methods can be found here: [home_assistant_media_player.md](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md)
53
+
54
+
49
55
  TODO list
50
56
 
51
- * Create a release on PyPI
52
- * Release a docker image
53
57
  * Improve error handling when deleting message with 'retain' set. WARNING:dbus2mqtt.mqtt_client:on_message: Unexpected payload, expecting json, topic=dbus2mqtt/org.mpris.MediaPlayer2/command, payload=, error=Expecting value: line 1 column 1 (char 0)
54
58
  * Property set only works the first time, need to restart after which the first set will work again
55
59
 
@@ -94,17 +98,17 @@ MQTT__USERNAME=
94
98
  MQTT__PASSWORD=
95
99
  ```
96
100
 
97
- ### Running from source
98
-
99
- To run dbus2mqtt from source (requires uv to be installed)
101
+ ### Install and run dbus2mqtt
100
102
 
101
103
  ```bash
102
- uv run main.py --config config.yaml
104
+ python -m pip install dbus2mqtt
105
+ dbus2mqtt --config config.yaml
103
106
  ```
104
107
 
108
+
105
109
  ### Run using docker with auto start behavior
106
110
 
107
- To build and run dbus2mqtt using Docker with the [home_assistant_media_player.yaml](docs/examples/home_assistant_media_player.yaml) example from this repository
111
+ To build and run dbus2mqtt using Docker with the [home_assistant_media_player.yaml](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.yaml) example from this repository.
108
112
 
109
113
  ```bash
110
114
  # setup configuration
@@ -112,9 +116,6 @@ mkdir -p $HOME/.config/dbus2mqtt
112
116
  cp docs/examples/home_assistant_media_player.yaml $HOME/.config/dbus2mqtt/config.yaml
113
117
  cp .env.example $HOME/.config/dbus2mqtt/.env
114
118
 
115
- # build image
116
- docker build -t jwnmulder/dbus2mqtt:latest .
117
-
118
119
  # run image and automatically start on reboot
119
120
  docker run --detach --name dbus2mqtt \
120
121
  --volume "$HOME"/.config/dbus2mqtt:"$HOME"/.config/dbus2mqtt \
@@ -133,7 +134,7 @@ sudo docker logs dbus2mqtt -f
133
134
 
134
135
  ## Examples
135
136
 
136
- This repository contains some examples under [docs/examples](docs/examples.md). The most complete one being [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md)
137
+ This repository contains examples under [docs/examples](https://github.com/jwnmulder/dbus2mqtt/blob/main//docs/examples.md). The most complete one being [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md)
137
138
 
138
139
  ## Configuration reference
139
140
 
@@ -216,8 +217,8 @@ dbus:
216
217
 
217
218
  ## Flows
218
219
 
219
- TODO: Document flows, for now see the [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md) example
220
+ TODO: Document flows, for now see the [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md) example
220
221
 
221
222
  ## Jinja templating
222
223
 
223
- TODO: Document Jinja templating, for now see the [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md) example
224
+ TODO: Document Jinja templating, for now see the [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md) example
@@ -1,7 +1,5 @@
1
1
  # dbus2mqtt
2
2
 
3
- > **⚠️ Warning:** This project has no releases yet. Running from source works. Docker images and Python packages are planned but not yet available.
4
-
5
3
  **dbus2mqtt** is a Python application that bridges **Linux D-Bus** with **MQTT**.
6
4
  It lets you forward D-Bus signals and properties to MQTT topics, call D-Bus methods via MQTT messages, and shape payloads using flexible **Jinja2 templating**.
7
5
 
@@ -15,10 +13,15 @@ This makes it easy to integrate Linux desktop services or system signals into MQ
15
13
  * 📡 Expose **D-Bus methods** for remote control via MQTT messages.
16
14
  * 🏠 Includes example configurations for **MPRIS** and **Home Assistant Media Player** integration.
17
15
 
16
+ ## Project status
17
+
18
+ **dbus2mqtt** is considered stable for the use-cases it has been tested against, and is actively being developed. Documentation is continuously being improved.
19
+
20
+ Initial testing has focused on MPRIS integration. A table of tested MPRIS players and their supported methods can be found here: [home_assistant_media_player.md](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md)
21
+
22
+
18
23
  TODO list
19
24
 
20
- * Create a release on PyPI
21
- * Release a docker image
22
25
  * Improve error handling when deleting message with 'retain' set. WARNING:dbus2mqtt.mqtt_client:on_message: Unexpected payload, expecting json, topic=dbus2mqtt/org.mpris.MediaPlayer2/command, payload=, error=Expecting value: line 1 column 1 (char 0)
23
26
  * Property set only works the first time, need to restart after which the first set will work again
24
27
 
@@ -63,17 +66,17 @@ MQTT__USERNAME=
63
66
  MQTT__PASSWORD=
64
67
  ```
65
68
 
66
- ### Running from source
67
-
68
- To run dbus2mqtt from source (requires uv to be installed)
69
+ ### Install and run dbus2mqtt
69
70
 
70
71
  ```bash
71
- uv run main.py --config config.yaml
72
+ python -m pip install dbus2mqtt
73
+ dbus2mqtt --config config.yaml
72
74
  ```
73
75
 
76
+
74
77
  ### Run using docker with auto start behavior
75
78
 
76
- To build and run dbus2mqtt using Docker with the [home_assistant_media_player.yaml](docs/examples/home_assistant_media_player.yaml) example from this repository
79
+ To build and run dbus2mqtt using Docker with the [home_assistant_media_player.yaml](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.yaml) example from this repository.
77
80
 
78
81
  ```bash
79
82
  # setup configuration
@@ -81,9 +84,6 @@ mkdir -p $HOME/.config/dbus2mqtt
81
84
  cp docs/examples/home_assistant_media_player.yaml $HOME/.config/dbus2mqtt/config.yaml
82
85
  cp .env.example $HOME/.config/dbus2mqtt/.env
83
86
 
84
- # build image
85
- docker build -t jwnmulder/dbus2mqtt:latest .
86
-
87
87
  # run image and automatically start on reboot
88
88
  docker run --detach --name dbus2mqtt \
89
89
  --volume "$HOME"/.config/dbus2mqtt:"$HOME"/.config/dbus2mqtt \
@@ -102,7 +102,7 @@ sudo docker logs dbus2mqtt -f
102
102
 
103
103
  ## Examples
104
104
 
105
- This repository contains some examples under [docs/examples](docs/examples.md). The most complete one being [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md)
105
+ This repository contains examples under [docs/examples](https://github.com/jwnmulder/dbus2mqtt/blob/main//docs/examples.md). The most complete one being [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md)
106
106
 
107
107
  ## Configuration reference
108
108
 
@@ -185,8 +185,8 @@ dbus:
185
185
 
186
186
  ## Flows
187
187
 
188
- TODO: Document flows, for now see the [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md) example
188
+ TODO: Document flows, for now see the [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md) example
189
189
 
190
190
  ## Jinja templating
191
191
 
192
- TODO: Document Jinja templating, for now see the [MPRIS to Home Assistant Media Player integration](docs/examples/home_assistant_media_player.md) example
192
+ TODO: Document Jinja templating, for now see the [MPRIS to Home Assistant Media Player integration](https://github.com/jwnmulder/dbus2mqtt/blob/main/docs/examples/home_assistant_media_player.md) example
@@ -2,9 +2,12 @@
2
2
 
3
3
  # First, build the application in the `/app` directory.
4
4
  # See `Dockerfile` for details.
5
- FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
5
+ FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
6
6
  ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
7
7
 
8
+ ARG PRETEND_VERSION
9
+ ENV SETUPTOOLS_SCM_PRETEND_VERSION=${PRETEND_VERSION}
10
+
8
11
  # Disable Python downloads, because we want to use the system interpreter
9
12
  # across both images. If using a managed Python version, it needs to be
10
13
  # copied from the build image into the final image; see `standalone.Dockerfile`
@@ -21,9 +24,8 @@ ADD src/ pyproject.toml uv.lock .python-version README.md /app
21
24
  RUN --mount=type=cache,target=/root/.cache/uv \
22
25
  uv sync --frozen --no-dev
23
26
 
24
-
25
27
  # Then, use a final image without uv
26
- FROM python:3.12-slim-bookworm
28
+ FROM python:3.13-slim-bookworm
27
29
  # It is important to use the image that matches the builder, as the path to the
28
30
  # Python executable must be the same, e.g., using `python:3.12-slim-bookworm`
29
31
  # will fail.
@@ -0,0 +1,10 @@
1
+ FROM python:3.13-slim-bookworm
2
+
3
+ WORKDIR /app
4
+
5
+ ARG DBUS2MQTT_VERSION=latest
6
+
7
+ RUN pip install --no-cache-dir dbus2mqtt=="$DBUS2MQTT_VERSION"
8
+
9
+ ENTRYPOINT ["python", "-m", "dbus2mqtt"]
10
+ CMD ["--help"]
@@ -1,49 +1,74 @@
1
1
  # Mediaplayer integration with Home Assistant
2
2
 
3
- Trying out this example
3
+ With dbus2mqtt as a bridge between MPRIS players and Home Assistant, it becomes possible to control Linux based media players via Home Assistant.
4
4
 
5
- ```bash
6
- uv run dbus2mqtt --config docs/home_assistant_media_player.yaml
7
- ```
5
+ The Media Player Remote Interfacing Specification (MPRIS) is a standard for controlling Linux media players. It provides a mechanism for compliant media players discovery, basic playback and media player state control as well as a tracklist interface which is used to add context to the current item.
6
+
7
+ Pre-requisites:
8
8
 
9
- This example shows how this dbus2mqtt can act as a bridge between the MPRIS player and Home Assistant.
9
+ * Home-Assistant with a working MQTT setup, the [media_player.template](https://github.com/Sennevds/media_player.template/tree/master) plugin installed and a working MQTT setup
10
+ plugins installed
10
11
 
11
12
  Features:
12
13
 
13
14
  * dbus subscription using `org.mpris.MediaPlayer2.*` wildcard to support multiple concurrent MRPIS players
14
15
  * Every 5 seconds, the state if the `first` known MPRIS player is published to MQTT topic `dbus2mqtt/org.mpris.MediaPlayer2/state`
15
16
  * Every MPRIS property update immediately publishes the state to MQTT topic `dbus2mqtt/org.mpris.MediaPlayer2/state`
16
- * Support for player commands (see table below)
17
+ * Support for player commands (see below)
18
+
19
+ Configuration activities
20
+
21
+ * MQTT Sensor and player configuration in Home Assistant (see below)
22
+ * dbus2mqtt setup using the supplied `home_assistant_media_player.yaml`
23
+
24
+ Execute the following command to run dbus2mqtt with the example configuration in this repository.
25
+
26
+ ```bash
27
+ dbus2mqtt --config docs/examples/home_assistant_media_player.yaml
28
+ ```
29
+
30
+
31
+ ## Tested configurations
32
+
33
+ The following setup is known to work with Home Assistant.
17
34
 
18
- ## Player Commands
35
+ | Application | Play<br />Pause<br /> | Stop | Next<br />Previous | Seek<br />SetPosition | Volume | Quit | Media Info | Media Image |
36
+ |--------------|-----------------------|------|--------------------|------|--------|------|------------|-------------|
37
+ | `Firefox` | ✅ | ✅ | ✅ | ✅ | | ❌ | ✅ | Youtube only |
38
+ | `VLC` | | | | | | | | | |
19
39
 
20
- The following table lists the supported player commands, their descriptions, and an example JSON payload for invoking them via MQTT.
40
+ ## Player commands
21
41
 
22
- dbus methods can be invoked by sendig the JSON payload to MQTT topic `dbus2mqtt/org.mpris.MediaPlayer2/command`. Method calls will be done for all matching players
42
+ The following table lists player commands, their descriptions, and an example JSON payload for invoking them via MQTT.
23
43
 
24
- | Interface | Method | Description | Example JSON Payload |
25
- |---------------------------------|------------|------------------------------------------|------------------------------------------------------------------------------------|
26
- | `org.mpris.MediaPlayer2.Player` | `Pause` | Pauses playback | `{ "method": "Pause" }` |
27
- | `org.mpris.MediaPlayer2.Player` | `Play` | Starts playback | `{ "method": "Play" }` |
28
- | `org.mpris.MediaPlayer2.Player` | `PlayPause`| Toggles between play and pause | `{ "method": "PlayPause" }` |
29
- | `org.mpris.MediaPlayer2.Player` | `OpenUri` | Opens a media file or stream by URI | `{ "method": "OpenUri", "args": ["<URI>"] }` |
30
- | `org.mpris.MediaPlayer2.Player` | `Stop` | Stops playback | `{ "method": "Stop" }` |
31
- | `org.mpris.MediaPlayer2` | `Quit` | Quits the media player | `{ "method": "Quit" }` |
44
+ Dbus methods can be invoked by sendig the JSON payload to MQTT topic `dbus2mqtt/org.mpris.MediaPlayer2/command`. Method calls will be done for all matching players
32
45
 
33
- Replace `<URI>` in the `OpenUri` payload with the desired media URI.
46
+ | Interface | Method<br />Property | Description | Example MQTT JSON Payload |
47
+ |---------------------------------|---------------|------------------------------------------|------------------------------------------------|
48
+ | `org.mpris.MediaPlayer2.Player` | `Play` | Starts playback | `{ "method": "Play" }` |
49
+ | `org.mpris.MediaPlayer2.Player` | `Pause` | Pauses playback | `{ "method": "Pause" }` |
50
+ | `org.mpris.MediaPlayer2.Player` | `PlayPause` | Toggles between play and pause | `{ "method": "PlayPause" }` |
51
+ | `org.mpris.MediaPlayer2.Player` | `Next` | Next | `{ "method": "Next" }` |
52
+ | `org.mpris.MediaPlayer2.Player` | `Previous` | Previous | `{ "method": "Previous" }` |
53
+ | `org.mpris.MediaPlayer2.Player` | `Stop` | Stops playback | `{ "method": "Stop" }` |
54
+ | `org.mpris.MediaPlayer2.Player` | `Seek` | Seek forward or backward in micro seconds | `{ "method": "Seek", "args": [60000000] }` |
55
+ | `org.mpris.MediaPlayer2.Player` | `Volume` | Set volume | `{ "property": "Volume", "value": 50 }` |
56
+ | `org.mpris.MediaPlayer2.Player` | `SetPosition` | Set / seek to position in micro seconds. First arguments needs to be trackid which can be determined via Metadata.mpris:trackid | `{ "method": "SetPosition", "args": ["/org/mpris/MediaPlayer2/firefox", 170692139] }` |
57
+ | `org.mpris.MediaPlayer2` | `Quit` | Quits the media player | `{ "method": "Quit" }` |
34
58
 
35
- For an overview of MPRIS commands have a look at <https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html>
59
+ For an overview of MPRIS commands have a look at <https://mpris2.readthedocs.io/en/latest/interfaces.html#mpris2.MediaPlayer2>
36
60
 
37
61
  ## Home Assistant configuration
38
62
 
39
- Example Home Assistant configuration is based upon <https://github.com/Sennevds/media_player.template/tree/master>
63
+ The configuration shown below creates a few components in Home Assistant
40
64
 
41
- Create the MQTT sensor for topic `dbus2mqtt/org.mpris.MediaPlayer2/state` and the Media Player as shown below
65
+ * Media Player
66
+ * MQTT sensor listening on topic `dbus2mqtt/org.mpris.MediaPlayer2/state`
42
67
 
43
68
  ```yaml
44
69
  mqtt:
45
70
  sensor:
46
- - name: "MPRIS Media Player"
71
+ - name: MPRIS Media Player
47
72
  state_topic: dbus2mqtt/org.mpris.MediaPlayer2/state
48
73
  json_attributes_topic: dbus2mqtt/org.mpris.MediaPlayer2/state
49
74
  value_template: >-
@@ -62,7 +87,7 @@ media_player:
62
87
  - platform: media_player_template
63
88
  media_players:
64
89
  mpris_media_player:
65
- # device_class: receiver
90
+ device_class: generic
66
91
  friendly_name: MPRIS Media Player
67
92
  value_template: "{{ states('sensor.mpris_media_player') }}"
68
93
 
@@ -80,7 +105,7 @@ media_player:
80
105
  media_image_url_template: >-
81
106
  {{ state_attr('sensor.mpris_media_player', 'Metadata')['xesam:url']
82
107
  | regex_replace(
83
- find='https:\/\/www\\.youtube\\.com\/watch\\?v=(.*)',
108
+ find='https:\/\/www\\.youtube\\.com\/watch\\?v=([^&]+).*',
84
109
  replace='https://img.youtube.com/vi/\\1/maxresdefault.jpg'
85
110
  )
86
111
  }}
@@ -119,7 +144,8 @@ media_player:
119
144
  service: mqtt.publish
120
145
  data:
121
146
  topic: dbus2mqtt/org.mpris.MediaPlayer2/command
122
- payload: '{"method": "Seek", "args": [{{ position | int }}] }'
147
+ payload: >-
148
+ { "method": "SetPosition", "args": ["{{ state_attr('sensor.mpris_media_player', 'Metadata')['mpris:trackid'] }}", {{ position | int }}] }
123
149
  set_volume:
124
150
  service: mqtt.publish
125
151
  data:
@@ -7,12 +7,13 @@ dbus:
7
7
 
8
8
  - bus_name: org.mpris.MediaPlayer2.*
9
9
  path: /org/mpris/MediaPlayer2
10
- # https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html
10
+ # https://mpris2.readthedocs.io/en/latest/interfaces.html#mpris2.MediaPlayer2
11
11
 
12
12
  interfaces:
13
13
  - interface: org.freedesktop.DBus.Properties
14
14
  signals:
15
15
  - signal: PropertiesChanged
16
+ # TODO: Determine if we should filter here or in flows? The only consumers right now are the flows
16
17
  filter: "{{ args[0] == 'org.mpris.MediaPlayer2.Player' }}"
17
18
  methods:
18
19
  - method: GetAll
@@ -31,6 +32,7 @@ dbus:
31
32
  - method: Next
32
33
  - method: Previous
33
34
  - method: Seek
35
+ - method: SetPosition
34
36
  - method: PlayPause
35
37
  - method: OpenUri
36
38
 
@@ -40,16 +42,17 @@ dbus:
40
42
  - type: bus_name_added
41
43
  - type: schedule
42
44
  interval: {seconds: 5}
43
- # - type: dbus_signal
44
- # interface: org.freedesktop.DBus.Properties
45
- # signal: PropertiesChanged
45
+ - type: dbus_signal
46
+ interface: org.freedesktop.DBus.Properties
47
+ signal: PropertiesChanged
46
48
  # filter: "{{ args[0] == 'org.mpris.MediaPlayer2.Player' }}"
47
49
  actions:
48
50
  - type: context_set
49
51
  context:
50
52
  mpris_bus_name: '{{ dbus_list("org.mpris.MediaPlayer2.*") | first }}'
51
- # player_properties: |
52
- # {{ dbus_call(mpris_bus_name, path, 'org.freedesktop.DBus.Properties', 'GetAll', ['org.mpris.MediaPlayer2.Player']) | to_yaml }}
53
+ # TODO: This would be a nice addition to avoid repetition
54
+ # player_properties: |
55
+ # {{ dbus_call(mpris_bus_name, path, 'org.freedesktop.DBus.Properties', 'GetAll', ['org.mpris.MediaPlayer2.Player']) | to_yaml }}
53
56
  path: /org/mpris/MediaPlayer2
54
57
  - type: mqtt_publish
55
58
  topic: dbus2mqtt/org.mpris.MediaPlayer2/state
@@ -61,7 +64,7 @@ dbus:
61
64
  - name: "MPRIS player removed"
62
65
  triggers:
63
66
  - type: bus_name_removed
64
- # filter: # CHECK FOR LAST ONE #
67
+ # filter: # TODO: Check if this is the last or inactive one #
65
68
  actions:
66
69
  - type: mqtt_publish
67
70
  topic: dbus2mqtt/org.mpris.MediaPlayer2/state
@@ -25,6 +25,7 @@ classifiers = [
25
25
 
26
26
  "Intended Audience :: Developers",
27
27
  "Operating System :: POSIX :: Linux",
28
+ "License :: OSI Approved :: MIT License",
28
29
 
29
30
  # Supported Python versions
30
31
  "Programming Language :: Python :: 3",
@@ -125,7 +125,7 @@ class DbusConfig:
125
125
  def get_subscription_configs(self, bus_name: str, path: str) -> list[SubscriptionConfig]:
126
126
  res: list[SubscriptionConfig] = []
127
127
  for subscription in self.subscriptions:
128
- if fnmatch.fnmatchcase(bus_name, subscription.bus_name) and fnmatch.fnmatchcase(path, subscription.path):
128
+ if fnmatch.fnmatchcase(bus_name, subscription.bus_name) and path == subscription.path:
129
129
  res.append(subscription)
130
130
  return res
131
131
 
@@ -124,7 +124,7 @@ class DbusClient:
124
124
 
125
125
  on_signal_method_name = "on_" + camel_to_snake(signal_config.signal)
126
126
  dbus_signal_state = {
127
- "bus_name_subscriptions": bus_name_subscriptions,
127
+ "bus_name": bus_name,
128
128
  "path": path,
129
129
  "interface_name": interface.name,
130
130
  "subscription_config": subscription_config,
@@ -354,6 +354,8 @@ class DbusClient:
354
354
 
355
355
  async def _handle_on_dbus_signal(self, signal: DbusSignalWithState):
356
356
 
357
+ logger.debug(f"dbus_signal: signal={signal.signal_config.signal}, args={signal.args}, bus_name={signal.bus_name}, path={signal.path}, interface={signal.interface_name}")
358
+
357
359
  for flow in signal.subscription_config.flows:
358
360
  for trigger in flow.triggers:
359
361
  if trigger.type == "dbus_signal" and signal.signal_config.signal == trigger.signal:
@@ -366,7 +368,7 @@ class DbusClient:
366
368
 
367
369
  if matches_filter:
368
370
  context = {
369
- "bus_name": signal.bus_name_subscriptions.bus_name,
371
+ "bus_name": signal.bus_name,
370
372
  "path": signal.path,
371
373
  "interface": signal.interface_name,
372
374
  "args": signal.args
@@ -394,8 +396,8 @@ class DbusClient:
394
396
  return
395
397
 
396
398
  logger.debug(f"on_mqtt_msg: topic={msg.topic}, payload={json.dumps(msg.payload)}")
397
- calls_done: list[str] = []
398
- properties_set: list[str] = []
399
+ matched_method = False
400
+ matched_property = False
399
401
 
400
402
  payload_method = msg.payload.get("method")
401
403
  payload_method_args = msg.payload.get("args") or []
@@ -417,27 +419,27 @@ class DbusClient:
417
419
  # filter configured method, configured topic, ...
418
420
  if method.method == payload_method:
419
421
  interface = proxy_object.get_interface(name=interface_config.interface)
422
+ matched_method = True
420
423
 
421
424
  try:
422
425
  logger.info(f"on_mqtt_msg: method={method.method}, args={payload_method_args}, bus_name={bus_name}, path={path}, interface={interface_config.interface}")
423
426
  await self.call_dbus_interface_method(interface, method.method, payload_method_args)
424
- calls_done.append(method.method)
425
427
  except Exception as e:
426
- logger.warning(f"on_mqtt_msg: method={method.method}, bus_name={bus_name} failed, exception={e}")
428
+ logger.warning(f"on_mqtt_msg: method={method.method}, args={payload_method_args}, bus_name={bus_name} failed, exception={e}")
427
429
 
428
430
  for property in interface_config.properties:
429
431
  # filter configured property, configured topic, ...
430
432
  if property.property == payload_property:
431
433
  interface = proxy_object.get_interface(name=interface_config.interface)
434
+ matched_property = True
432
435
 
433
436
  try:
434
437
  logger.info(f"on_mqtt_msg: property={property.property}, value={payload_value}, bus_name={bus_name}, path={path}, interface={interface_config.interface}")
435
438
  await self.set_dbus_interface_property(interface, property.property, payload_value)
436
- properties_set.append(property.property)
437
439
  except Exception as e:
438
- logger.warning(f"on_mqtt_msg: property={property.property}, bus_name={bus_name} failed, exception={e}")
440
+ logger.warning(f"on_mqtt_msg: property={property.property}, value={payload_value}, bus_name={bus_name} failed, exception={e}")
439
441
 
440
- if len(calls_done) == 0 and len(properties_set) == 0:
442
+ if not matched_method and not matched_property:
441
443
  if payload_method:
442
444
  logger.info(f"No configured or active dbus subscriptions for topic={msg.topic}, method={payload_method}, active bus_names={list(self.subscriptions.keys())}")
443
445
  if payload_property:
@@ -15,7 +15,7 @@ def unwrap_dbus_object(o):
15
15
  json_obj = json.loads(res)
16
16
  return json_obj
17
17
 
18
- def unwrap_dbus_objects(*args):
18
+ def unwrap_dbus_objects(args):
19
19
  res = [unwrap_dbus_object(o) for o in args]
20
20
  return res
21
21
 
@@ -13,7 +13,6 @@ from dbus2mqtt.config import (
13
13
  SignalConfig,
14
14
  SubscriptionConfig,
15
15
  )
16
- from dbus2mqtt.dbus.dbus_types import BusNameSubscriptions
17
16
 
18
17
  logger = logging.getLogger(__name__)
19
18
 
@@ -26,7 +25,7 @@ class MqttMessage:
26
25
 
27
26
  @dataclass
28
27
  class DbusSignalWithState:
29
- bus_name_subscriptions: BusNameSubscriptions
28
+ bus_name: str
30
29
  path: str
31
30
  interface_name: str
32
31
  subscription_config: SubscriptionConfig
@@ -1,4 +1,6 @@
1
1
 
2
+ import dbus_next.aio as dbus_aio
3
+
2
4
  from pydantic import SecretStr
3
5
 
4
6
  from dbus2mqtt import AppContext, config
@@ -8,8 +10,9 @@ from dbus2mqtt.config import (
8
10
  FlowTriggerConfig,
9
11
  InterfaceConfig,
10
12
  )
13
+ from dbus2mqtt.dbus.dbus_client import DbusClient
11
14
  from dbus2mqtt.event_broker import EventBroker
12
- from dbus2mqtt.flow.flow_processor import FlowProcessor
15
+ from dbus2mqtt.flow.flow_processor import FlowProcessor, FlowScheduler
13
16
  from dbus2mqtt.template.templating import TemplateEngine
14
17
 
15
18
 
@@ -51,3 +54,17 @@ def mocked_flow_processor(app_context: AppContext, trigger_config: FlowTriggerCo
51
54
 
52
55
  processor = FlowProcessor(app_context)
53
56
  return processor, flow_config
57
+
58
+ class MockedMessageBus(dbus_aio.message_bus.MessageBus):
59
+ def _setup_socket(self):
60
+ self._stream = ""
61
+ self._sock = ""
62
+ self._fd = ""
63
+
64
+ def mocked_dbus_client(app_context: AppContext):
65
+
66
+ bus = MockedMessageBus(bus_address="unix:path=/run/user/1000/bus")
67
+ flow_scheduler = FlowScheduler(app_context)
68
+
69
+ dbus_client = DbusClient(app_context, bus, flow_scheduler)
70
+ return dbus_client
@@ -0,0 +1,49 @@
1
+
2
+ import dbus_next.introspection as dbus_intr
3
+ import dbus_next.signature as dbus_signature
4
+
5
+ from dbus_next.constants import ArgDirection
6
+
7
+ from tests import mocked_app_context, mocked_dbus_client
8
+
9
+
10
+ def test_signal_handler_unwrap_args():
11
+
12
+ app_context = mocked_app_context()
13
+ dbus_client = mocked_dbus_client(app_context)
14
+
15
+ dbus_signal = dbus_intr.Signal("PropertiesChanged", [
16
+ dbus_intr.Arg(name="interface_name", signature="s", direction=[ArgDirection.IN]),
17
+ dbus_intr.Arg(name="changed_properties", signature="a{sv}", direction=[ArgDirection.IN]),
18
+ dbus_intr.Arg(name="invalidated_properties", signature="as", direction=[ArgDirection.IN])
19
+ ])
20
+
21
+ dbus_signal_state = {}
22
+ dbus_signal_state = {
23
+ "bus_name": "org.mpris.MediaPlayer2.vlc",
24
+ "path": "/org/mpris/MediaPlayer2",
25
+ "interface_name": "org.freedesktop.DBus.Properties",
26
+ "subscription_config": None, # subscription_config,
27
+ "signal_config": None, # signal_config,
28
+ }
29
+
30
+ handler = dbus_client._dbus_next_signal_handler(dbus_signal, dbus_signal_state)
31
+ assert handler is not None
32
+
33
+ args = [
34
+ "org.mpris.MediaPlayer2.Player",
35
+ {
36
+ "CanPause": dbus_signature.Variant("b", True)
37
+ },
38
+ []
39
+ ]
40
+
41
+ # Invoke with wrapped arguments
42
+ handler(*args)
43
+
44
+ # Check if message is published on the event_broker
45
+ mqtt_message = app_context.event_broker.dbus_signal_queue.sync_q.get_nowait()
46
+
47
+ # message args should be unwrapped
48
+ assert mqtt_message is not None
49
+ assert mqtt_message.args == ["org.mpris.MediaPlayer2.Player", {"CanPause" : True}, []]
@@ -1,8 +1,5 @@
1
-
2
- import dbus_next.aio as dbus_aio
3
1
  import pytest
4
2
 
5
- from dbus2mqtt import AppContext
6
3
  from dbus2mqtt.config import (
7
4
  FlowActionContextSetConfig,
8
5
  FlowTriggerBusNameAddedConfig,
@@ -10,10 +7,8 @@ from dbus2mqtt.config import (
10
7
  FlowTriggerDbusSignalConfig,
11
8
  SignalConfig,
12
9
  )
13
- from dbus2mqtt.dbus.dbus_client import DbusClient
14
- from dbus2mqtt.event_broker import BusNameSubscriptions, DbusSignalWithState
15
- from dbus2mqtt.flow.flow_processor import FlowScheduler
16
- from tests import mocked_app_context, mocked_flow_processor
10
+ from dbus2mqtt.event_broker import DbusSignalWithState
11
+ from tests import mocked_app_context, mocked_dbus_client, mocked_flow_processor
17
12
 
18
13
 
19
14
  @pytest.mark.asyncio
@@ -32,7 +27,7 @@ async def test_bus_name_added_trigger():
32
27
  )
33
28
  ])
34
29
 
35
- dbus_client = _mocked_dbus_client(app_context)
30
+ dbus_client = mocked_dbus_client(app_context)
36
31
 
37
32
  subscription_config = app_context.config.dbus.subscriptions[0]
38
33
 
@@ -64,7 +59,7 @@ async def test_bus_name_removed_trigger():
64
59
  )
65
60
  ])
66
61
 
67
- dbus_client = _mocked_dbus_client(app_context)
62
+ dbus_client = mocked_dbus_client(app_context)
68
63
 
69
64
  subscription_config = app_context.config.dbus.subscriptions[0]
70
65
 
@@ -104,10 +99,10 @@ async def test_dbus_signal_trigger():
104
99
 
105
100
  subscription_config = app_context.config.dbus.subscriptions[0]
106
101
 
107
- dbus_client = _mocked_dbus_client(app_context)
102
+ dbus_client = mocked_dbus_client(app_context)
108
103
 
109
104
  signal = DbusSignalWithState(
110
- bus_name_subscriptions=BusNameSubscriptions("test-bus-name"),
105
+ bus_name="test-bus-name",
111
106
  path="/",
112
107
  interface_name=subscription_config.interfaces[0].interface,
113
108
  subscription_config=subscription_config,
@@ -132,17 +127,3 @@ async def test_dbus_signal_trigger():
132
127
  "interface": "test-interface-name",
133
128
  "args": ["first-arg", "second-arg"]
134
129
  }
135
-
136
- class MockedMessageBus(dbus_aio.message_bus.MessageBus):
137
- def _setup_socket(self):
138
- self._stream = ""
139
- self._sock = ""
140
- self._fd = ""
141
-
142
- def _mocked_dbus_client(app_context: AppContext):
143
-
144
- bus = MockedMessageBus(bus_address="unix:path=/run/user/1000/bus")
145
- flow_scheduler = FlowScheduler(app_context)
146
-
147
- dbus_client = DbusClient(app_context, bus, flow_scheduler)
148
- return dbus_client
@@ -1,6 +0,0 @@
1
- .env
2
-
3
- .ruff_cache
4
- .venv
5
- dist
6
- __pycache__
@@ -1 +0,0 @@
1
- 3.12
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes