stinger-python-utils 0.1.9__tar.gz → 0.2.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.
- stinger_python_utils-0.2.0/.agents/skills/release/SKILL.md +67 -0
- stinger_python_utils-0.2.0/.github/workflows/python-tests.yml +30 -0
- stinger_python_utils-0.2.0/.vscode/settings.json +10 -0
- stinger_python_utils-0.2.0/PKG-INFO +84 -0
- stinger_python_utils-0.2.0/README.md +73 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/pyproject.toml +2 -12
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/src/stinger_python_utils/message_creator.py +152 -23
- stinger_python_utils-0.2.0/tests/test_message_creator.py +611 -0
- stinger_python_utils-0.2.0/uv.lock +1603 -0
- stinger_python_utils-0.1.9/.github/workflows/python-tests.yml +0 -51
- stinger_python_utils-0.1.9/.vscode/settings.json +0 -4
- stinger_python_utils-0.1.9/PKG-INFO +0 -276
- stinger_python_utils-0.1.9/README.md +0 -261
- stinger_python_utils-0.1.9/src/stinger_python_utils/mcp/__init__.py +0 -20
- stinger_python_utils-0.1.9/src/stinger_python_utils/mcp/__main__.py +0 -58
- stinger_python_utils-0.1.9/src/stinger_python_utils/mcp/plugin.py +0 -220
- stinger_python_utils-0.1.9/src/stinger_python_utils/mcp/server.py +0 -633
- stinger_python_utils-0.1.9/uv.lock +0 -2052
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/.github/workflows/python37.yml +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/.gitignore +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/LICENSE +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/src/stinger_python_utils/__init__.py +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/src/stinger_python_utils/return_codes.py +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/test/__init__.py +0 -0
- {stinger_python_utils-0.1.9 → stinger_python_utils-0.2.0}/test/test_message_creator.py +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: "Release stinger-python-utils. Use when: releasing a new version, cutting a release, bumping the version, publishing, shipping, preparing a release, running pre-release checks."
|
|
4
|
+
argument-hint: "optional notes or release context"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Release stinger-python-utils
|
|
8
|
+
|
|
9
|
+
Runs pre-release checks, bumps the version in `pyproject.toml`, then offers to commit and push.
|
|
10
|
+
|
|
11
|
+
## Procedure
|
|
12
|
+
|
|
13
|
+
### 1. Run mypy
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
uv run mypy src/ tests/
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If mypy reports errors, fix them before continuing. Do not proceed until mypy is clean.
|
|
20
|
+
|
|
21
|
+
### 2. Run pytest
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
uv run pytest
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If any tests fail, fix them before continuing. Do not proceed until all tests pass.
|
|
28
|
+
|
|
29
|
+
### 3. Bump the version
|
|
30
|
+
|
|
31
|
+
Read the current version from `pyproject.toml`. Then ask the user:
|
|
32
|
+
|
|
33
|
+
> The current version is `X.Y.Z`. How would you like to bump it?
|
|
34
|
+
> - **patch** → `X.Y.Z+1`
|
|
35
|
+
> - **minor** → `X.Y+1.0`
|
|
36
|
+
> - **major** → `X+1.0.0`
|
|
37
|
+
> - **manual** → enter a custom version string
|
|
38
|
+
|
|
39
|
+
Apply the chosen version to the `version` field in `pyproject.toml`.
|
|
40
|
+
|
|
41
|
+
### 4. Confirm commit and push
|
|
42
|
+
|
|
43
|
+
Ask the user:
|
|
44
|
+
|
|
45
|
+
> Ready to commit and push `vX.Y.Z` to `origin/main`?
|
|
46
|
+
> - **Yes** — stage `pyproject.toml`, commit with message `chore: bump version to X.Y.Z`, then push to `origin main`
|
|
47
|
+
> - **No** — stop here; leave the version bump in place for the user to handle manually
|
|
48
|
+
|
|
49
|
+
Only run `git add`, `git commit`, and `git push` if the user explicitly confirms.
|
|
50
|
+
|
|
51
|
+
### 5. Build
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
uv build
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If the build fails, report the error and stop. Do not proceed to publish.
|
|
58
|
+
|
|
59
|
+
### 6. Confirm publish
|
|
60
|
+
|
|
61
|
+
Ask the user:
|
|
62
|
+
|
|
63
|
+
> Build succeeded. Publish `vX.Y.Z` to PyPI with `uv publish`?
|
|
64
|
+
> - **Yes** — run `uv publish`
|
|
65
|
+
> - **No** — stop here; the built artifacts are in `dist/`
|
|
66
|
+
|
|
67
|
+
Only run `uv publish` if the user explicitly confirms.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Python Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
# Python 3.7 requires a completely different setup because it is very EOL.
|
|
15
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- name: Install UV
|
|
19
|
+
uses: astral-sh/setup-uv@v7
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
- name: Install project
|
|
23
|
+
run: |
|
|
24
|
+
uv sync --locked --dev
|
|
25
|
+
- name: Run unit tests
|
|
26
|
+
run: |
|
|
27
|
+
uv run pytest
|
|
28
|
+
- name: Mypy Type Check
|
|
29
|
+
run: |
|
|
30
|
+
uv run mypy --check-untyped-defs ./src/
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: stinger-python-utils
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Common utilities for Stinger Python services.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.7
|
|
8
|
+
Requires-Dist: pydantic>=2.5.3
|
|
9
|
+
Requires-Dist: pyqttier>=0.2.0
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# stinger-python-utils
|
|
13
|
+
|
|
14
|
+
Shared utilities for Stinger Python services, providing convenient message creation for MQTT communication.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv add stinger-python-utils
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## MessageCreator
|
|
25
|
+
|
|
26
|
+
`MessageCreator` is a utility class for creating MQTT messages with standardized properties and payloads.
|
|
27
|
+
|
|
28
|
+
### Basic Usage
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from pydantic import BaseModel
|
|
32
|
+
from stinger_python_utils.message_creator import MessageCreator
|
|
33
|
+
|
|
34
|
+
class MyPayload(BaseModel):
|
|
35
|
+
name: str
|
|
36
|
+
value: int
|
|
37
|
+
|
|
38
|
+
payload = MyPayload(name="test", value=42)
|
|
39
|
+
message = MessageCreator.signal_message("my/topic", payload)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Methods
|
|
43
|
+
|
|
44
|
+
| Method | Purpose | Return Code |
|
|
45
|
+
|--------|---------|-------------|
|
|
46
|
+
| `signal_message(topic, payload)` | Send a signal with one-time delivery | QoS 1, no retain |
|
|
47
|
+
| `status_message(topic, payload, expiry_seconds)` | Send status that expires | QoS 1, retained, with expiry |
|
|
48
|
+
| `error_response_message(topic, return_code, correlation_id, debug_info)` | Error response to a request | QoS 1, user properties: `ReturnCode` |
|
|
49
|
+
| `response_message(topic, payload, return_code, correlation_id)` | Successful response to a request | QoS 1, user properties: `ReturnCode` |
|
|
50
|
+
| `property_state_message(topic, payload, state_version)` | Publish property state | QoS 1, retained, JSON content type |
|
|
51
|
+
| `property_update_request_message(topic, payload, version, response_topic, correlation_id)` | Request property update | QoS 1, user property: `PropertyVersion` |
|
|
52
|
+
| `property_response_message(topic, payload, version, return_code, correlation_id, debug_info)` | Respond to property update | QoS 1, user properties: `ReturnCode`, `PropertyVersion` |
|
|
53
|
+
| `request_message(topic, payload, response_topic, correlation_id)` | Send a request (auto-generates UUID if no correlation_id) | QoS 1, auto correlation ID |
|
|
54
|
+
|
|
55
|
+
### Example: Request/Response Pattern
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from pydantic import BaseModel
|
|
59
|
+
from stinger_python_utils.message_creator import MessageCreator
|
|
60
|
+
|
|
61
|
+
class Request(BaseModel):
|
|
62
|
+
action: str
|
|
63
|
+
|
|
64
|
+
request = Request(action="start")
|
|
65
|
+
msg = MessageCreator.request_message(
|
|
66
|
+
"devices/cmd",
|
|
67
|
+
request,
|
|
68
|
+
response_topic="devices/response"
|
|
69
|
+
)
|
|
70
|
+
# Returns a Message with auto-generated correlation ID
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Example: Error Response
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
msg = MessageCreator.error_response_message(
|
|
77
|
+
"devices/response",
|
|
78
|
+
return_code=500,
|
|
79
|
+
correlation_id="req-123",
|
|
80
|
+
debug_info="Device not found"
|
|
81
|
+
)
|
|
82
|
+
# User properties include: ReturnCode=500, DebugInfo=Device not found
|
|
83
|
+
```
|
|
84
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# stinger-python-utils
|
|
2
|
+
|
|
3
|
+
Shared utilities for Stinger Python services, providing convenient message creation for MQTT communication.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv add stinger-python-utils
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## MessageCreator
|
|
14
|
+
|
|
15
|
+
`MessageCreator` is a utility class for creating MQTT messages with standardized properties and payloads.
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from pydantic import BaseModel
|
|
21
|
+
from stinger_python_utils.message_creator import MessageCreator
|
|
22
|
+
|
|
23
|
+
class MyPayload(BaseModel):
|
|
24
|
+
name: str
|
|
25
|
+
value: int
|
|
26
|
+
|
|
27
|
+
payload = MyPayload(name="test", value=42)
|
|
28
|
+
message = MessageCreator.signal_message("my/topic", payload)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Methods
|
|
32
|
+
|
|
33
|
+
| Method | Purpose | Return Code |
|
|
34
|
+
|--------|---------|-------------|
|
|
35
|
+
| `signal_message(topic, payload)` | Send a signal with one-time delivery | QoS 1, no retain |
|
|
36
|
+
| `status_message(topic, payload, expiry_seconds)` | Send status that expires | QoS 1, retained, with expiry |
|
|
37
|
+
| `error_response_message(topic, return_code, correlation_id, debug_info)` | Error response to a request | QoS 1, user properties: `ReturnCode` |
|
|
38
|
+
| `response_message(topic, payload, return_code, correlation_id)` | Successful response to a request | QoS 1, user properties: `ReturnCode` |
|
|
39
|
+
| `property_state_message(topic, payload, state_version)` | Publish property state | QoS 1, retained, JSON content type |
|
|
40
|
+
| `property_update_request_message(topic, payload, version, response_topic, correlation_id)` | Request property update | QoS 1, user property: `PropertyVersion` |
|
|
41
|
+
| `property_response_message(topic, payload, version, return_code, correlation_id, debug_info)` | Respond to property update | QoS 1, user properties: `ReturnCode`, `PropertyVersion` |
|
|
42
|
+
| `request_message(topic, payload, response_topic, correlation_id)` | Send a request (auto-generates UUID if no correlation_id) | QoS 1, auto correlation ID |
|
|
43
|
+
|
|
44
|
+
### Example: Request/Response Pattern
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from pydantic import BaseModel
|
|
48
|
+
from stinger_python_utils.message_creator import MessageCreator
|
|
49
|
+
|
|
50
|
+
class Request(BaseModel):
|
|
51
|
+
action: str
|
|
52
|
+
|
|
53
|
+
request = Request(action="start")
|
|
54
|
+
msg = MessageCreator.request_message(
|
|
55
|
+
"devices/cmd",
|
|
56
|
+
request,
|
|
57
|
+
response_topic="devices/response"
|
|
58
|
+
)
|
|
59
|
+
# Returns a Message with auto-generated correlation ID
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Example: Error Response
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
msg = MessageCreator.error_response_message(
|
|
66
|
+
"devices/response",
|
|
67
|
+
return_code=500,
|
|
68
|
+
correlation_id="req-123",
|
|
69
|
+
debug_info="Device not found"
|
|
70
|
+
)
|
|
71
|
+
# User properties include: ReturnCode=500, DebugInfo=Device not found
|
|
72
|
+
```
|
|
73
|
+
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "stinger-python-utils"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Common utilities for Stinger Python services."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -15,16 +15,6 @@ dependencies = [
|
|
|
15
15
|
"pyqttier>=0.2.0",
|
|
16
16
|
]
|
|
17
17
|
|
|
18
|
-
[project.optional-dependencies]
|
|
19
|
-
mcp = [
|
|
20
|
-
"mcp>=1.27.0; python_version >= '3.10'",
|
|
21
|
-
"stevedore>=5.7; python_version >= '3.10'",
|
|
22
|
-
"uvicorn>=0.44.0; python_version >= '3.10'",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
[project.scripts]
|
|
26
|
-
stinger-mcp-server = "stinger_python_utils.mcp.__main__:main"
|
|
27
|
-
|
|
28
18
|
[tool.uv]
|
|
29
19
|
managed = true
|
|
30
20
|
|
|
@@ -32,5 +22,5 @@ managed = true
|
|
|
32
22
|
dev = [
|
|
33
23
|
"black>=23.3.0",
|
|
34
24
|
"mypy>=1.4.1",
|
|
35
|
-
"pytest>=7.0.0",
|
|
25
|
+
"pytest>=7.0.0; python_version >= '3.10'",
|
|
36
26
|
]
|
|
@@ -16,27 +16,73 @@ class MessageCreator:
|
|
|
16
16
|
|
|
17
17
|
@classmethod
|
|
18
18
|
def signal_message(cls, topic: str, payload: BaseModel) -> Message:
|
|
19
|
+
return cls.binary_signal_message(
|
|
20
|
+
topic,
|
|
21
|
+
payload.model_dump_json(by_alias=True).encode("utf-8"),
|
|
22
|
+
"application/json",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def binary_signal_message(cls, topic: str, payload: bytes, content_type: str) -> Message:
|
|
19
27
|
cls._validate_topic(topic)
|
|
20
28
|
return Message(
|
|
21
29
|
topic=topic,
|
|
22
|
-
payload=payload
|
|
30
|
+
payload=payload,
|
|
23
31
|
qos=1,
|
|
24
32
|
retain=False,
|
|
25
|
-
content_type=
|
|
33
|
+
content_type=content_type,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def command_message(cls, topic: str, payload: BaseModel, qos: int = 2) -> Message:
|
|
38
|
+
return cls.binary_command_message(
|
|
39
|
+
topic,
|
|
40
|
+
payload.model_dump_json(by_alias=True).encode("utf-8"),
|
|
41
|
+
"application/json",
|
|
42
|
+
qos=qos,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def binary_command_message(
|
|
47
|
+
cls, topic: str, payload: bytes, content_type: str, qos: int = 2
|
|
48
|
+
) -> Message:
|
|
49
|
+
"""
|
|
50
|
+
A command is a signal in reverse: the client publishes it to the server and never
|
|
51
|
+
learns whether it was acted on. There is therefore no response topic and no
|
|
52
|
+
correlation data on the message.
|
|
53
|
+
"""
|
|
54
|
+
cls._validate_topic(topic)
|
|
55
|
+
return Message(
|
|
56
|
+
topic=topic,
|
|
57
|
+
payload=payload,
|
|
58
|
+
qos=qos,
|
|
59
|
+
retain=False,
|
|
60
|
+
content_type=content_type,
|
|
26
61
|
)
|
|
27
62
|
|
|
28
63
|
@classmethod
|
|
29
64
|
def status_message(
|
|
30
|
-
cls, topic, status_message: BaseModel, expiry_seconds: int
|
|
65
|
+
cls, topic: str, status_message: BaseModel, expiry_seconds: int
|
|
66
|
+
) -> Message:
|
|
67
|
+
return cls.binary_status_message(
|
|
68
|
+
topic,
|
|
69
|
+
status_message.model_dump_json(by_alias=True).encode("utf-8"),
|
|
70
|
+
"application/json",
|
|
71
|
+
expiry_seconds=expiry_seconds,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def binary_status_message(
|
|
76
|
+
cls, topic: str, payload: bytes, content_type: str, expiry_seconds: int
|
|
31
77
|
) -> Message:
|
|
32
78
|
cls._validate_topic(topic)
|
|
33
79
|
return Message(
|
|
34
80
|
topic=topic,
|
|
35
|
-
payload=
|
|
81
|
+
payload=payload,
|
|
36
82
|
qos=1,
|
|
37
83
|
retain=True,
|
|
38
84
|
message_expiry_interval=expiry_seconds,
|
|
39
|
-
content_type=
|
|
85
|
+
content_type=content_type,
|
|
40
86
|
)
|
|
41
87
|
|
|
42
88
|
@classmethod
|
|
@@ -46,9 +92,14 @@ class MessageCreator:
|
|
|
46
92
|
return_code: Union[int, MethodReturnCode],
|
|
47
93
|
correlation_id: Union[str, bytes, None] = None,
|
|
48
94
|
debug_info: Optional[str] = None,
|
|
95
|
+
content_type: str = "application/json",
|
|
49
96
|
) -> Message:
|
|
50
97
|
"""
|
|
51
98
|
This could be used for a response to a request, but where there was an error fulfilling the request.
|
|
99
|
+
|
|
100
|
+
An error carries no data -- the return code and any debug info travel in MQTT user
|
|
101
|
+
properties -- so the body is an empty JSON object for a JSON response and empty
|
|
102
|
+
bytes for any other content type, since a protobuf consumer would reject "{}".
|
|
52
103
|
"""
|
|
53
104
|
cls._validate_topic(topic)
|
|
54
105
|
rc = (
|
|
@@ -58,7 +109,7 @@ class MessageCreator:
|
|
|
58
109
|
)
|
|
59
110
|
msg_obj = Message(
|
|
60
111
|
topic=topic,
|
|
61
|
-
payload=b"{}",
|
|
112
|
+
payload=b"{}" if content_type == "application/json" else b"",
|
|
62
113
|
qos=1,
|
|
63
114
|
retain=False,
|
|
64
115
|
correlation_data=(
|
|
@@ -67,7 +118,7 @@ class MessageCreator:
|
|
|
67
118
|
else correlation_id
|
|
68
119
|
),
|
|
69
120
|
user_properties={"ReturnCode": str(rc)},
|
|
70
|
-
content_type=
|
|
121
|
+
content_type=content_type,
|
|
71
122
|
)
|
|
72
123
|
if (
|
|
73
124
|
debug_info is not None and msg_obj.user_properties is not None
|
|
@@ -86,19 +137,32 @@ class MessageCreator:
|
|
|
86
137
|
"""
|
|
87
138
|
This could be used for a successful response to a request.
|
|
88
139
|
"""
|
|
89
|
-
cls._validate_topic(response_topic, "response_topic")
|
|
90
140
|
if isinstance(response_obj, BaseModel):
|
|
91
141
|
payload = response_obj.model_dump_json(by_alias=True).encode("utf-8")
|
|
92
142
|
elif isinstance(response_obj, str):
|
|
93
143
|
payload = response_obj.encode("utf-8")
|
|
94
144
|
else:
|
|
95
145
|
payload = response_obj
|
|
146
|
+
return cls.binary_response_message(
|
|
147
|
+
response_topic, payload, "application/json", return_code, correlation_id
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def binary_response_message(
|
|
152
|
+
cls,
|
|
153
|
+
response_topic: str,
|
|
154
|
+
payload: bytes,
|
|
155
|
+
content_type: str,
|
|
156
|
+
return_code: Union[int, MethodReturnCode],
|
|
157
|
+
correlation_id: Union[str, bytes, None] = None,
|
|
158
|
+
) -> Message:
|
|
159
|
+
cls._validate_topic(response_topic, "response_topic")
|
|
96
160
|
rc = (
|
|
97
161
|
return_code.value
|
|
98
162
|
if isinstance(return_code, MethodReturnCode)
|
|
99
163
|
else return_code
|
|
100
164
|
)
|
|
101
|
-
|
|
165
|
+
return Message(
|
|
102
166
|
topic=response_topic,
|
|
103
167
|
payload=payload,
|
|
104
168
|
qos=1,
|
|
@@ -109,9 +173,8 @@ class MessageCreator:
|
|
|
109
173
|
else correlation_id
|
|
110
174
|
),
|
|
111
175
|
user_properties={"ReturnCode": str(rc)},
|
|
112
|
-
content_type=
|
|
176
|
+
content_type=content_type,
|
|
113
177
|
)
|
|
114
|
-
return msg_obj
|
|
115
178
|
|
|
116
179
|
@classmethod
|
|
117
180
|
def property_state_message(
|
|
@@ -120,13 +183,24 @@ class MessageCreator:
|
|
|
120
183
|
"""
|
|
121
184
|
Creates a retained message representing the state/value of a property.
|
|
122
185
|
"""
|
|
186
|
+
return cls.binary_property_state_message(
|
|
187
|
+
topic,
|
|
188
|
+
state_obj.model_dump_json(by_alias=True).encode("utf-8"),
|
|
189
|
+
"application/json",
|
|
190
|
+
state_version,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
@classmethod
|
|
194
|
+
def binary_property_state_message(
|
|
195
|
+
cls, topic: str, payload: bytes, content_type: str, state_version: Optional[int] = None
|
|
196
|
+
) -> Message:
|
|
123
197
|
cls._validate_topic(topic)
|
|
124
198
|
msg_obj = Message(
|
|
125
199
|
topic=topic,
|
|
126
|
-
payload=
|
|
200
|
+
payload=payload,
|
|
127
201
|
qos=1,
|
|
128
202
|
retain=True,
|
|
129
|
-
content_type=
|
|
203
|
+
content_type=content_type,
|
|
130
204
|
)
|
|
131
205
|
if state_version is not None:
|
|
132
206
|
msg_obj.user_properties = {"PropertyVersion": str(state_version)}
|
|
@@ -144,14 +218,33 @@ class MessageCreator:
|
|
|
144
218
|
"""
|
|
145
219
|
Creates a message representing a request to update a property.
|
|
146
220
|
"""
|
|
221
|
+
return cls.binary_property_update_request_message(
|
|
222
|
+
topic,
|
|
223
|
+
property_obj.model_dump_json(by_alias=True).encode("utf-8"),
|
|
224
|
+
"application/json",
|
|
225
|
+
version,
|
|
226
|
+
response_topic,
|
|
227
|
+
correlation_id,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
@classmethod
|
|
231
|
+
def binary_property_update_request_message(
|
|
232
|
+
cls,
|
|
233
|
+
topic: str,
|
|
234
|
+
payload: bytes,
|
|
235
|
+
content_type: str,
|
|
236
|
+
version: str,
|
|
237
|
+
response_topic: str,
|
|
238
|
+
correlation_id: Union[str, bytes, None] = None,
|
|
239
|
+
) -> Message:
|
|
147
240
|
cls._validate_topic(topic)
|
|
148
241
|
cls._validate_topic(response_topic, "response_topic")
|
|
149
|
-
|
|
242
|
+
return Message(
|
|
150
243
|
topic=topic,
|
|
151
|
-
payload=
|
|
244
|
+
payload=payload,
|
|
152
245
|
qos=1,
|
|
153
246
|
retain=False,
|
|
154
|
-
content_type=
|
|
247
|
+
content_type=content_type,
|
|
155
248
|
response_topic=response_topic,
|
|
156
249
|
correlation_data=(
|
|
157
250
|
correlation_id.encode("utf-8")
|
|
@@ -160,7 +253,6 @@ class MessageCreator:
|
|
|
160
253
|
),
|
|
161
254
|
user_properties={"PropertyVersion": str(version)},
|
|
162
255
|
)
|
|
163
|
-
return msg_obj
|
|
164
256
|
|
|
165
257
|
@classmethod
|
|
166
258
|
def property_response_message(
|
|
@@ -175,6 +267,27 @@ class MessageCreator:
|
|
|
175
267
|
"""
|
|
176
268
|
Creates a message representing a response to a property update request.
|
|
177
269
|
"""
|
|
270
|
+
return cls.binary_property_response_message(
|
|
271
|
+
response_topic,
|
|
272
|
+
property_obj.model_dump_json(by_alias=True).encode("utf-8"),
|
|
273
|
+
"application/json",
|
|
274
|
+
version,
|
|
275
|
+
return_code,
|
|
276
|
+
correlation_id,
|
|
277
|
+
debug_info,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
@classmethod
|
|
281
|
+
def binary_property_response_message(
|
|
282
|
+
cls,
|
|
283
|
+
response_topic: str,
|
|
284
|
+
payload: bytes,
|
|
285
|
+
content_type: str,
|
|
286
|
+
version: str,
|
|
287
|
+
return_code: Union[int, MethodReturnCode],
|
|
288
|
+
correlation_id: Union[str, bytes, None] = None,
|
|
289
|
+
debug_info: Optional[str] = None,
|
|
290
|
+
) -> Message:
|
|
178
291
|
cls._validate_topic(response_topic, "response_topic")
|
|
179
292
|
rc = (
|
|
180
293
|
return_code.value
|
|
@@ -183,10 +296,10 @@ class MessageCreator:
|
|
|
183
296
|
)
|
|
184
297
|
msg_obj = Message(
|
|
185
298
|
topic=response_topic,
|
|
186
|
-
payload=
|
|
299
|
+
payload=payload,
|
|
187
300
|
qos=1,
|
|
188
301
|
retain=False,
|
|
189
|
-
content_type=
|
|
302
|
+
content_type=content_type,
|
|
190
303
|
correlation_data=(
|
|
191
304
|
correlation_id.encode("utf-8")
|
|
192
305
|
if isinstance(correlation_id, str)
|
|
@@ -210,22 +323,38 @@ class MessageCreator:
|
|
|
210
323
|
request_obj: BaseModel,
|
|
211
324
|
response_topic: str,
|
|
212
325
|
correlation_id: Union[str, bytes, None] = None,
|
|
326
|
+
) -> Message:
|
|
327
|
+
return cls.binary_request_message(
|
|
328
|
+
topic,
|
|
329
|
+
request_obj.model_dump_json(by_alias=True).encode("utf-8"),
|
|
330
|
+
"application/json",
|
|
331
|
+
response_topic,
|
|
332
|
+
correlation_id,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
@classmethod
|
|
336
|
+
def binary_request_message(
|
|
337
|
+
cls,
|
|
338
|
+
topic: str,
|
|
339
|
+
payload: bytes,
|
|
340
|
+
content_type: str,
|
|
341
|
+
response_topic: str,
|
|
342
|
+
correlation_id: Union[str, bytes, None] = None,
|
|
213
343
|
) -> Message:
|
|
214
344
|
cls._validate_topic(topic)
|
|
215
345
|
cls._validate_topic(response_topic, "response_topic")
|
|
216
346
|
if correlation_id is None:
|
|
217
347
|
correlation_id = str(uuid.uuid4())
|
|
218
|
-
|
|
348
|
+
return Message(
|
|
219
349
|
topic=topic,
|
|
220
|
-
payload=
|
|
350
|
+
payload=payload,
|
|
221
351
|
qos=1,
|
|
222
352
|
retain=False,
|
|
223
353
|
response_topic=response_topic,
|
|
224
|
-
content_type=
|
|
354
|
+
content_type=content_type,
|
|
225
355
|
correlation_data=(
|
|
226
356
|
correlation_id.encode("utf-8")
|
|
227
357
|
if isinstance(correlation_id, str)
|
|
228
358
|
else correlation_id
|
|
229
359
|
),
|
|
230
360
|
)
|
|
231
|
-
return msg_obj
|