stinger-ipc 0.0.25__tar.gz → 0.0.27__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_ipc-0.0.25/stinger_ipc.egg-info → stinger_ipc-0.0.27}/PKG-INFO +1 -1
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/pyproject.toml +1 -1
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27/stinger_ipc.egg-info}/PKG-INFO +1 -1
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/client.cpp.jinja2 +4 -4
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/server.py.jinja2 +138 -18
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/server/Cargo.toml.jinja2 +1 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/server/examples/server.rs.jinja2 +7 -9
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/server/src/lib.rs.jinja2 +11 -11
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/LICENSE +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/README.md +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/setup.cfg +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stinger_ipc.egg-info/SOURCES.txt +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stinger_ipc.egg-info/dependency_links.txt +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stinger_ipc.egg-info/entry_points.txt +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stinger_ipc.egg-info/requires.txt +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stinger_ipc.egg-info/top_level.txt +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/__init__.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/args.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/asyncapi.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/components.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/connection.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/exceptions.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/interface.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/lang_symb.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/schema/schema.yaml +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/CMakeLists.txt.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/examples/client_main.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/examples/server_main.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/broker.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/client.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/enums.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/property_structs.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/return_types.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/server.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/structs.hpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/partials/args.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/partials/deserialize.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/partials/serialize.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/broker.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/property_structs.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/server.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/structs.cpp.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/html/app.js.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/html/index.html.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/html/styles.css.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/markdown/index.md.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/__init__.py.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/client.py.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/connection.py.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/interface_types.py.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/method_codes.py.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/pyproject.toml.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/Cargo.toml.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/Cargo.toml.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/examples/client.rs.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/src/lib.rs.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/Cargo.toml.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/examples/pub_and_recv.rs.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/src/lib.rs.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/src/payloads.rs.jinja2 +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/__init__.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/cli.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/cpp_generator.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/markdown_generator.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/python_generator.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/tools/rust_generator.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/topic.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_args.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_enum.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_examples.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_interface.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_signal.py +0 -0
- {stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/tests/test_topics.py +0 -0
@@ -45,7 +45,7 @@ constexpr const char {{stinger.cpp.client_class_name}}::INTERFACE_VERSION[];
|
|
45
45
|
{%-endfor%}
|
46
46
|
|
47
47
|
{%-for prop_name, prop in stinger.properties.items() %}
|
48
|
-
_{{prop_name | lowerCamelCase}}PropertySubscriptionId = _broker->Subscribe("{{prop.
|
48
|
+
_{{prop_name | lowerCamelCase}}PropertySubscriptionId = _broker->Subscribe("{{prop.value_topic}}", 1);
|
49
49
|
{%-endfor%}
|
50
50
|
}
|
51
51
|
|
@@ -116,7 +116,7 @@ void {{stinger.cpp.client_class_name}}::_receiveMessage(
|
|
116
116
|
{%-endfor%}{# for methods #}
|
117
117
|
|
118
118
|
{%-for prop_name, prop in stinger.properties.items() %}
|
119
|
-
{%if not loop.first%}else {%endif%}if ((mqttProps.subscriptionId && (*mqttProps.subscriptionId == _{{prop_name | lowerCamelCase}}PropertySubscriptionId)) || topic == "{{prop.
|
119
|
+
{%if not loop.first%}else {%endif%}if ((mqttProps.subscriptionId && (*mqttProps.subscriptionId == _{{prop_name | lowerCamelCase}}PropertySubscriptionId)) || topic == "{{prop.value_topic}}")
|
120
120
|
{
|
121
121
|
_receive{{prop_name | UpperCamelCase}}PropertyUpdate(topic, payload, mqttProps.propertyVersion);
|
122
122
|
}
|
@@ -164,6 +164,7 @@ void {{stinger.cpp.client_class_name}}::_handle{{method_name|UpperCamelCase}}Res
|
|
164
164
|
const std::string &correlationId)
|
165
165
|
{
|
166
166
|
std::cout << "In response handler for " << topic << " with correlationId=" << correlationId << std::endl;
|
167
|
+
{%if method.return_value_type is not false%}
|
167
168
|
rapidjson::Document doc;
|
168
169
|
rapidjson::ParseResult ok = doc.Parse(payload.c_str());
|
169
170
|
if (!ok)
|
@@ -171,11 +172,10 @@ void {{stinger.cpp.client_class_name}}::_handle{{method_name|UpperCamelCase}}Res
|
|
171
172
|
//Log("Could not JSON parse {{method_name}} signal payload.");
|
172
173
|
throw std::runtime_error(rapidjson::GetParseError_En(ok.Code()));
|
173
174
|
}
|
174
|
-
|
175
175
|
if (!doc.IsObject()) {
|
176
176
|
throw std::runtime_error("Received payload is not an object");
|
177
177
|
}
|
178
|
-
|
178
|
+
{%endif%}
|
179
179
|
boost::uuids::uuid correlationIdUuid = boost::lexical_cast<boost::uuids::uuid>(correlationId);
|
180
180
|
auto promiseItr = _pending{{method_name|UpperCamelCase}}MethodCalls.find(correlationIdUuid);
|
181
181
|
if (promiseItr != _pending{{method_name|UpperCamelCase}}MethodCalls.end())
|
@@ -7,15 +7,31 @@ This is the Server for the {{stinger.name}} interface.
|
|
7
7
|
|
8
8
|
import json
|
9
9
|
import logging
|
10
|
-
|
10
|
+
import threading
|
11
|
+
from dataclasses import dataclass, field
|
11
12
|
logging.basicConfig(level=logging.DEBUG)
|
12
13
|
|
13
|
-
from typing import Callable, Dict, Any, Optional, List
|
14
|
+
from typing import Callable, Dict, Any, Optional, List, Generic, TypeVar
|
14
15
|
from connection import BrokerConnection
|
15
16
|
from method_codes import *
|
16
17
|
import {{stinger.get_enum_module_name()}} as {{stinger.get_enum_module_alias()}}
|
17
18
|
{%macro method_type_annotation(method) %}Callable[[{%if method.arg_list | length > 0%}{%for arg in method.arg_list%}{{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}{%else%}None{%endif%}], {{method.return_value_python_type}}]{%endmacro%}
|
18
19
|
|
20
|
+
T = TypeVar('T')
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class PropertyControls(Generic[T]):
|
24
|
+
value: T | None = None
|
25
|
+
mutex = threading.Lock()
|
26
|
+
version: int = -1
|
27
|
+
subscription_id: int | None = None
|
28
|
+
callbacks: List[Callable[[T], None]] = field(default_factory=list)
|
29
|
+
|
30
|
+
@dataclass
|
31
|
+
class MethodControls:
|
32
|
+
subscription_id: int | None = None
|
33
|
+
callback: Optional[Callable] = None
|
34
|
+
|
19
35
|
class {{stinger.python.server_class_name}}:
|
20
36
|
|
21
37
|
def __init__(self, connection: BrokerConnection):
|
@@ -25,18 +41,15 @@ class {{stinger.python.server_class_name}}:
|
|
25
41
|
self._conn = connection
|
26
42
|
self._conn.set_message_callback(self._receive_message)
|
27
43
|
self._conn.set_last_will(topic="{{stinger.interface_info.0}}", payload=None, qos=1, retain=True)
|
28
|
-
{%for prop_name,
|
29
|
-
self._property_{{prop_name}} =
|
30
|
-
self._conn.subscribe("{{
|
31
|
-
self.changed_value_callback_for_{{pprop_name}} = None
|
32
|
-
self._publish_interface_info()
|
44
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
45
|
+
self._property_{{prop_name|snake_case}}: PropertyControls[{%if prop.arg_list | length == 1%}{{prop.arg_list[0].python_class}}{%else%}{{prop.python_class}}{%endif%}, {%for arg in prop.arg_list %}{{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}] = PropertyControls()
|
46
|
+
self._property_{{prop_name|snake_case}}.subscription_id = self._conn.subscribe("{{prop.update_topic}}")
|
33
47
|
{%endfor-%}
|
34
|
-
{%-for method in stinger.methods.
|
35
|
-
self.
|
36
|
-
{
|
37
|
-
{%for method_name, method in stinger.methods.items()-%}
|
38
|
-
self._{{method_name|snake_case}}_method_handler: Optional[{{method_type_annotation(method)}}] = None
|
48
|
+
{%-for method_name, method in stinger.methods.items()%}
|
49
|
+
self._method_{{method_name|snake_case}} = MethodControls()
|
50
|
+
self._method_{{method_name|snake_case}}.subscription_id = self._conn.subscribe("{{method.topic}}")
|
39
51
|
{%endfor%}
|
52
|
+
self._publish_interface_info()
|
40
53
|
|
41
54
|
def _receive_message(self, topic: str, payload: str, properties: Dict[str, Any]):
|
42
55
|
""" This is the callback that is called whenever any message is received on a subscribed topic.
|
@@ -44,7 +57,7 @@ class {{stinger.python.server_class_name}}:
|
|
44
57
|
self._logger.debug("Received message to %s", topic)
|
45
58
|
{%if stinger.methods | length > 0 -%}
|
46
59
|
{%for method_name, method in stinger.methods.items()-%}
|
47
|
-
{%if not loop.first%}el{%endif%}if self._conn.is_topic_sub(topic, "{{method.topic}}"):
|
60
|
+
{%if not loop.first%}el{%endif%}if (properties.get('SubscriptionId', -1) == self._method_{{method_name|snake_case}}.subscription_id) or self._conn.is_topic_sub(topic, "{{method.topic}}"):
|
48
61
|
try:
|
49
62
|
payload_obj = json.loads(payload)
|
50
63
|
except json.decoder.JSONDecodeError:
|
@@ -52,7 +65,25 @@ class {{stinger.python.server_class_name}}:
|
|
52
65
|
else:
|
53
66
|
self._process_{{method_name | snake_case}}_call(topic, payload_obj, properties)
|
54
67
|
{%endfor%}
|
55
|
-
{%-
|
68
|
+
{%-endif%}
|
69
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
70
|
+
{%if not loop.first%}el{%endif%}if (properties.get('SubscriptionId', -1) == self._property_{{prop_name|snake_case}}.subscription_id) or self._conn.is_topic_sub(topic, "{{prop.update_topic}}"):
|
71
|
+
{%if prop.arg_list | length > 1 -%}
|
72
|
+
prop_value = {{prop.python_class}}.model_validate_json(payload)
|
73
|
+
{%else-%}
|
74
|
+
payload_obj = json.loads(payload)
|
75
|
+
prop_value = {{prop.arg_list[0].python_class}}(payload_obj["{{prop.arg_list[0].name}}"])
|
76
|
+
{%endif-%}
|
77
|
+
with self._property_{{prop_name|snake_case}}.mutex:
|
78
|
+
self._property_{{prop_name|snake_case}}.value = prop_value
|
79
|
+
self._property_{{prop_name|snake_case}}.version += 1
|
80
|
+
for callback in self._property_{{prop_name|snake_case}}.callbacks:
|
81
|
+
{%-if prop.arg_list | length > 1%}
|
82
|
+
callback({%for arg in prop.arg_list %}prop_value.{{arg.name|snake_case}}{%if not loop.last%}, {%endif%}{%endfor%})
|
83
|
+
{%-else%}
|
84
|
+
callback(prop_value)
|
85
|
+
{%-endif%}
|
86
|
+
{%endfor%}
|
56
87
|
|
57
88
|
def _publish_interface_info(self):
|
58
89
|
self._conn.publish("{{stinger.interface_info.0}}", '''{{stinger.interface_info.1 | tojson}}''', qos=1, retain=True)
|
@@ -78,8 +109,8 @@ class {{stinger.python.server_class_name}}:
|
|
78
109
|
def handle_{{method_name | snake_case}}(self, handler: {{method_type_annotation(method)}}):
|
79
110
|
""" This is a decorator to decorate a method that will handle the '{{method_name}}' method calls.
|
80
111
|
"""
|
81
|
-
if self.
|
82
|
-
self.
|
112
|
+
if self._method_{{method_name|snake_case}}.callback is None and handler is not None:
|
113
|
+
self._method_{{method_name|snake_case}}.callback = handler
|
83
114
|
else:
|
84
115
|
raise Exception("Method handler already set")
|
85
116
|
|
@@ -90,7 +121,7 @@ class {{stinger.python.server_class_name}}:
|
|
90
121
|
correlation_id = properties.get('CorrelationData') # type: Optional[bytes]
|
91
122
|
response_topic = properties.get('ResponseTopic') # type: Optional[str]
|
92
123
|
self._logger.info("Correlation Data %s", correlation_id)
|
93
|
-
if self.
|
124
|
+
if self._method_{{method_name|snake_case}}.callback is not None:
|
94
125
|
method_args = [] # type: List[Any]
|
95
126
|
{%for arg in method.arg_list -%}
|
96
127
|
if "{{arg.name}}" in payload:
|
@@ -114,7 +145,7 @@ class {{stinger.python.server_class_name}}:
|
|
114
145
|
return_json = ""
|
115
146
|
debug_msg = None # type: Optional[str]
|
116
147
|
try:
|
117
|
-
return_struct = self.
|
148
|
+
return_struct = self._method_{{method_name|snake_case}}.callback(*method_args)
|
118
149
|
self._logger.debug("Return value is %s", return_struct)
|
119
150
|
{%if method.return_value is false%}
|
120
151
|
return_json = "{}"
|
@@ -147,7 +178,65 @@ class {{stinger.python.server_class_name}}:
|
|
147
178
|
self._conn.publish(response_topic, return_json, qos=1, retain=False,
|
148
179
|
correlation_id=correlation_id, return_value=return_code, debug_info=debug_msg)
|
149
180
|
{%endfor%}
|
181
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
182
|
+
@property
|
183
|
+
def {{prop_name | snake_case}}(self) -> {{prop.python_class}}|None:
|
184
|
+
""" This property returns the last received value for the '{{prop_name}}' property.
|
185
|
+
"""
|
186
|
+
with self._property_{{prop_name|snake_case}}_mutex:
|
187
|
+
return self._property_{{prop_name|snake_case}}
|
150
188
|
|
189
|
+
@{{prop_name | snake_case}}.setter
|
190
|
+
def {{prop_name | snake_case}}(self, {%if prop.arg_list | length > 1%}value{%else%}{{prop.arg_list[0].name|snake_case}}{%endif%}: {{prop.python_class}}):
|
191
|
+
""" This property sets (publishes) a new value for the '{{prop_name}}' property.
|
192
|
+
"""
|
193
|
+
if not isinstance({%if prop.arg_list | length > 1%}value{%else%}{{prop.arg_list[0].name|snake_case}}{%endif%}, {{prop.python_class}}):
|
194
|
+
raise ValueError(f"The value must be {{prop.python_class}}.")
|
195
|
+
|
196
|
+
{%if prop.arg_list | length > 1%}
|
197
|
+
payload = value.model_dump_json()
|
198
|
+
{%else%}
|
199
|
+
payload = json.dumps({ "{{prop.arg_list[0].name}}": {{prop.arg_list[0].name|snake_case}} })
|
200
|
+
{%endif%}
|
201
|
+
|
202
|
+
if {%if prop.arg_list | length > 1%}value{%else%}{{prop.arg_list[0].name|snake_case}}{%endif%} != self._property_{{prop_name|snake_case}}.value:
|
203
|
+
with self._property_{{prop_name|snake_case}}.mutex:
|
204
|
+
self._property_{{prop_name|snake_case}}.value = {%if prop.arg_list | length > 1%}value{%else%}{{prop.arg_list[0].name|snake_case}}{%endif%}
|
205
|
+
self._property_{{prop_name|snake_case}}.version += 1
|
206
|
+
self._conn.publish("{{prop.value_topic}}", payload, qos=1, retain=True)
|
207
|
+
for callback in self._property_{{prop_name|snake_case}}.callbacks:
|
208
|
+
{%-if prop.arg_list | length > 1%}
|
209
|
+
callback({%for arg in prop.arg_list %}value.{{arg.name|snake_case}}{%if not loop.last%}, {%endif%}{%endfor%})
|
210
|
+
{%-else%}
|
211
|
+
callback({{prop.arg_list[0].name|snake_case}})
|
212
|
+
{%-endif%}
|
213
|
+
|
214
|
+
def set_{{prop_name | snake_case}}(self, {%for arg in prop.arg_list %}{{arg.name|snake_case}}: {{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}):
|
215
|
+
""" This method sets (publishes) a new value for the '{{prop_name}}' property.
|
216
|
+
"""
|
217
|
+
{%-for arg in prop.arg_list%}
|
218
|
+
if not isinstance({{arg.name|snake_case}}, {{arg.python_class}}){%if arg.optional%} and {{arg.name|snake_case}} is not None{%endif%}:
|
219
|
+
raise ValueError(f"The '{{arg.name|snake_case}}' value must be {{arg.python_type}}.")
|
220
|
+
{%-endfor%}
|
221
|
+
|
222
|
+
{%if prop.arg_list | length > 1%}
|
223
|
+
obj = stinger_types.{{prop.python_local_type}}({%for arg in prop.arg_list%}
|
224
|
+
{{arg.name}}={{arg.name|snake_case}},
|
225
|
+
{%endfor%}
|
226
|
+
)
|
227
|
+
{%else%}
|
228
|
+
obj = {{prop.arg_list[0].name | snake_case}}
|
229
|
+
{%endif%}
|
230
|
+
|
231
|
+
# Use the property.setter to do that actual work.
|
232
|
+
self.{{prop_name|snake_case}} = obj
|
233
|
+
|
234
|
+
def on_{{prop_name | snake_case}}_updates(self, handler: Callable[[{%for arg in prop.arg_list %}{{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}], None]):
|
235
|
+
""" This method registers a callback to be called whenever a new '{{prop_name}}' property update is received.
|
236
|
+
"""
|
237
|
+
if handler is not None:
|
238
|
+
self._property_{{prop_name|snake_case}}.callbacks.append(handler)
|
239
|
+
{%endfor%}
|
151
240
|
|
152
241
|
class {{stinger.python.server_class_name}}Builder:
|
153
242
|
"""
|
@@ -159,6 +248,9 @@ class {{stinger.python.server_class_name}}Builder:
|
|
159
248
|
{%for method_name, method in stinger.methods.items()%}
|
160
249
|
self._{{method_name|snake_case}}_method_handler: Optional[{{method_type_annotation(method)}}] = None
|
161
250
|
{%-endfor%}
|
251
|
+
{%for prop_name, property in stinger.properties.items()%}
|
252
|
+
self._{{prop_name|snake_case}}_property_callbacks: List[Callable[[{%for arg in property.arg_list %}{{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}], None]] = []
|
253
|
+
{%-endfor%}
|
162
254
|
{%for method_name, method in stinger.methods.items()%}
|
163
255
|
def handle_{{method_name | snake_case}}(self, handler: {{method_type_annotation(method)}}):
|
164
256
|
if self._{{method_name|snake_case}}_method_handler is None and handler is not None:
|
@@ -166,12 +258,22 @@ class {{stinger.python.server_class_name}}Builder:
|
|
166
258
|
else:
|
167
259
|
raise Exception("Method handler already set")
|
168
260
|
{%endfor%}
|
261
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
262
|
+
def on_{{prop_name | snake_case}}_updates(self, handler: Callable[[{%for arg in prop.arg_list %}{{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}], None]):
|
263
|
+
""" This method registers a callback to be called whenever a new '{{prop_name}}' property update is received.
|
264
|
+
"""
|
265
|
+
self._{{prop_name|snake_case}}_property_callbacks.append(handler)
|
266
|
+
{%endfor%}
|
169
267
|
def build(self) -> {{stinger.python.server_class_name}}:
|
170
268
|
new_server = {{stinger.python.server_class_name}}(self._conn)
|
171
269
|
{%for method_name, method in stinger.methods.items()%}
|
172
270
|
if self._{{method_name|snake_case}}_method_handler is not None:
|
173
271
|
new_server.handle_{{method_name|snake_case}}(self._{{method_name|snake_case}}_method_handler)
|
174
272
|
{%-endfor%}
|
273
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
274
|
+
for callback in self._{{prop_name|snake_case}}_property_callbacks:
|
275
|
+
new_server.on_{{prop_name|snake_case}}_updates(callback)
|
276
|
+
{%endfor%}
|
175
277
|
return new_server
|
176
278
|
|
177
279
|
if __name__ == '__main__':
|
@@ -187,6 +289,18 @@ if __name__ == '__main__':
|
|
187
289
|
conn = {{broker.class_name}}({%if broker.hostname is none%}'localhost', 1883{%endif%})
|
188
290
|
server = {{stinger.python.server_class_name}}(conn)
|
189
291
|
|
292
|
+
{%for prop_name, prop in stinger.properties.items()-%}
|
293
|
+
{%if prop.arg_list | length > 1%}
|
294
|
+
server.{{prop_name | snake_case}} = {{prop.python_class}}(
|
295
|
+
{%for arg in prop.arg_list%}
|
296
|
+
{{arg.name}}={{arg.get_random_example_value()}},
|
297
|
+
{%endfor%}
|
298
|
+
)
|
299
|
+
{%else%}
|
300
|
+
server.{{prop_name | snake_case}} = {{prop.arg_list[0].get_random_example_value()}}
|
301
|
+
{%endif%}
|
302
|
+
{%endfor%}
|
303
|
+
|
190
304
|
{%for method_name, method in stinger.methods.items()%}
|
191
305
|
@server.handle_{{method_name | snake_case}}
|
192
306
|
def {{method_name | snake_case}}({%for arg in method.arg_list%}{{arg.name}}: {{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}) -> {{method.return_value_python_type}}:
|
@@ -195,6 +309,12 @@ if __name__ == '__main__':
|
|
195
309
|
return {{method.get_return_value_random_example_value('python')}}
|
196
310
|
{%endfor%}
|
197
311
|
|
312
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
313
|
+
@server.on_{{prop_name | snake_case}}_updates
|
314
|
+
def on_{{prop_name | snake_case}}_update({%for arg in prop.arg_list %}{{arg.name}}: {{arg.python_type}}{%if not loop.last%}, {%endif%}{%endfor%}):
|
315
|
+
print(f"Received update for '{{prop_name}}' property: {%for arg in prop.arg_list %}{ {{arg.name}}= }{%if not loop.last%}, {%endif%}{%endfor%}")
|
316
|
+
{%endfor%}
|
317
|
+
|
198
318
|
print("Ctrl-C will stop the program.")
|
199
319
|
|
200
320
|
while True:
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/server/examples/server.rs.jinja2
RENAMED
@@ -10,9 +10,10 @@ use mqttier::MqttierClient;
|
|
10
10
|
use {{stinger.rust.server_package_name}}::{ {{stinger.rust.server_struct_name}}{%if stinger.methods|length>0%}, {{stinger.name | UpperCamelCase }}MethodHandlers{%endif%} };
|
11
11
|
use tokio::time::{sleep, Duration};
|
12
12
|
{%if stinger.methods|length > 0%}
|
13
|
-
|
14
|
-
|
15
|
-
use
|
13
|
+
use std::sync::Arc;
|
14
|
+
use tokio::sync::Mutex;
|
15
|
+
use async_trait::async_trait;
|
16
|
+
{%endif%}
|
16
17
|
#[allow(unused_imports)]
|
17
18
|
use {{stinger.rust.common_package_name}}::payloads::{MethodResultCode, *};
|
18
19
|
|
@@ -29,15 +30,16 @@ impl {{stinger.name | UpperCamelCase }}MethodImpl {
|
|
29
30
|
}
|
30
31
|
}
|
31
32
|
|
33
|
+
#[async_trait]
|
32
34
|
impl {{stinger.name | UpperCamelCase }}MethodHandlers for {{stinger.name | UpperCamelCase }}MethodImpl {
|
33
35
|
|
34
|
-
fn initialize(&mut self, server: {{stinger.rust.server_struct_name}}) -> Result<(), MethodResultCode> {
|
36
|
+
async fn initialize(&mut self, server: {{stinger.rust.server_struct_name}}) -> Result<(), MethodResultCode> {
|
35
37
|
self.server = Some(server.clone());
|
36
38
|
Ok(())
|
37
39
|
}
|
38
40
|
|
39
41
|
{%for method_name, method in stinger.methods.items()%}
|
40
|
-
fn handle_{{method_name|snake_case}}(&self, {%for arg in method.arg_list%}_{{arg.name|snake_case}}: {{arg.rust_type}}{%if not loop.last%}, {%endif%}{%endfor%}) -> Result<{{method.return_value_rust_type}}, MethodResultCode> {
|
42
|
+
async fn handle_{{method_name|snake_case}}(&self, {%for arg in method.arg_list%}_{{arg.name|snake_case}}: {{arg.rust_type}}{%if not loop.last%}, {%endif%}{%endfor%}) -> Result<{{method.return_value_rust_type}}, MethodResultCode> {
|
41
43
|
println!("Handling {{method_name}}");
|
42
44
|
{%-if method.return_value_type == 'struct'%}
|
43
45
|
let rv = {{method.return_value_rust_type}} {
|
@@ -58,12 +60,8 @@ impl {{stinger.name | UpperCamelCase }}MethodHandlers for {{stinger.name | Upper
|
|
58
60
|
self
|
59
61
|
}
|
60
62
|
}
|
61
|
-
|
62
|
-
|
63
63
|
{%endif%}
|
64
64
|
|
65
|
-
|
66
|
-
|
67
65
|
#[tokio::main]
|
68
66
|
async fn main() {
|
69
67
|
env_logger::Builder::from_default_env()
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/server/src/lib.rs.jinja2
RENAMED
@@ -13,9 +13,8 @@ use mqttier::{MqttierClient{%if stinger.methods|length > 0 or stinger.properties
|
|
13
13
|
use {{stinger.rust.common_package_name}}::payloads::{*, MethodResultCode};
|
14
14
|
use std::any::Any;
|
15
15
|
{%if stinger.methods|length > 0 %}
|
16
|
-
|
17
|
-
|
18
|
-
//pub use handler::{{stinger.name | UpperCamelCase }}MethodHandlers;
|
16
|
+
use async_trait::async_trait;
|
17
|
+
use tokio::sync::Mutex as AsyncMutex;
|
19
18
|
use std::sync::{Arc, Mutex};
|
20
19
|
{%endif%}
|
21
20
|
{%if stinger.methods|length > 0 or stinger.properties|length > 0 %}
|
@@ -68,7 +67,7 @@ pub struct {{stinger.rust.server_struct_name}} {
|
|
68
67
|
{%endif%}
|
69
68
|
{%if stinger.methods|length > 0 %}
|
70
69
|
/// Struct contains all the method handlers.
|
71
|
-
method_handlers: Arc<
|
70
|
+
method_handlers: Arc<AsyncMutex<Box<dyn {{stinger.name | UpperCamelCase }}MethodHandlers>>>,
|
72
71
|
{%endif%}
|
73
72
|
{%if stinger.properties|length > 0%}
|
74
73
|
/// Struct contains all the properties.
|
@@ -85,7 +84,7 @@ pub struct {{stinger.rust.server_struct_name}} {
|
|
85
84
|
}
|
86
85
|
|
87
86
|
impl {{stinger.rust.server_struct_name}} {
|
88
|
-
pub async fn new(connection: &mut MqttierClient{%if stinger.methods|length > 0%}, method_handlers: Arc<
|
87
|
+
pub async fn new(connection: &mut MqttierClient{%if stinger.methods|length > 0%}, method_handlers: Arc<AsyncMutex<Box<dyn {{stinger.name | UpperCamelCase }}MethodHandlers>>> {%endif%}) -> Self {
|
89
88
|
{%if stinger.methods|length > 0 or stinger.properties|length > 0 %}
|
90
89
|
// Create a channel for messages to get from the MqttierClient object to this {{stinger.rust.server_struct_name}} object.
|
91
90
|
// The Connection object uses a clone of the tx side of the channel.
|
@@ -152,7 +151,7 @@ impl {{stinger.rust.server_struct_name}} {
|
|
152
151
|
|
153
152
|
{%for method_name, method in stinger.methods.items()-%}
|
154
153
|
/// Handles a request message for the {{method_name}} method.
|
155
|
-
async fn handle_{{method_name|snake_case}}_request(publisher: MqttierClient, handlers: Arc<
|
154
|
+
async fn handle_{{method_name|snake_case}}_request(publisher: MqttierClient, handlers: Arc<AsyncMutex<Box<dyn {{stinger.name | UpperCamelCase }}MethodHandlers>>>, msg: ReceivedMessage) {
|
156
155
|
let opt_corr_data = msg.correlation_data;
|
157
156
|
let opt_resp_topic = msg.response_topic;
|
158
157
|
{%if method.arg_list | length > 0 -%}
|
@@ -161,8 +160,8 @@ impl {{stinger.rust.server_struct_name}} {
|
|
161
160
|
{%endif%}{# has arg_list #}
|
162
161
|
// call the method handler
|
163
162
|
let rv: Result<{{method.return_value_rust_type}}, MethodResultCode> = {
|
164
|
-
let handler_guard = handlers.lock().
|
165
|
-
|
163
|
+
let handler_guard = handlers.lock().await;
|
164
|
+
handler_guard.handle_{{method_name|snake_case}}({%for arg in method.arg_list%}payload.{{arg.name}}{%if not loop.last%}, {%endif%}{%endfor%}).await
|
166
165
|
};
|
167
166
|
|
168
167
|
if let Some(resp_topic) = opt_resp_topic {
|
@@ -267,7 +266,7 @@ impl {{stinger.rust.server_struct_name}} {
|
|
267
266
|
|
268
267
|
{%if stinger.methods|length > 0 -%}
|
269
268
|
let method_handlers = self.method_handlers.clone();
|
270
|
-
self.method_handlers.lock().
|
269
|
+
self.method_handlers.lock().await.initialize(self.clone()).await;
|
271
270
|
{%endif-%}
|
272
271
|
|
273
272
|
let sub_ids = self.subscription_ids.clone();
|
@@ -304,13 +303,14 @@ impl {{stinger.rust.server_struct_name}} {
|
|
304
303
|
|
305
304
|
}
|
306
305
|
{%if stinger.methods|length > 0 %}
|
306
|
+
#[async_trait]
|
307
307
|
pub trait {{stinger.name | UpperCamelCase }}MethodHandlers: Send + Sync {
|
308
308
|
|
309
|
-
fn initialize(&mut self, server: {{stinger.rust.server_struct_name}}) -> Result<(), MethodResultCode>;
|
309
|
+
async fn initialize(&mut self, server: {{stinger.rust.server_struct_name}}) -> Result<(), MethodResultCode>;
|
310
310
|
|
311
311
|
{%for method_name, method in stinger.methods.items()-%}
|
312
312
|
/// Pointer to a function to handle the {{method_name}} method request.
|
313
|
-
fn handle_{{method_name|snake_case}}(&self, {%for arg in method.arg_list%}{{arg.name|snake_case}}: {{arg.rust_type}}{%if not loop.last%}, {%endif%}{%endfor%}) -> Result<{{method.return_value_rust_type}}, MethodResultCode>;
|
313
|
+
async fn handle_{{method_name|snake_case}}(&self, {%for arg in method.arg_list%}{{arg.name|snake_case}}: {{arg.rust_type}}{%if not loop.last%}, {%endif%}{%endfor%}) -> Result<{{method.return_value_rust_type}}, MethodResultCode>;
|
314
314
|
|
315
315
|
{%endfor%}
|
316
316
|
|
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
|
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
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/examples/client_main.cpp.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/examples/server_main.cpp.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/broker.hpp.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/client.hpp.jinja2
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/return_types.hpp.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/server.hpp.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/include/structs.hpp.jinja2
RENAMED
File without changes
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/partials/deserialize.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/partials/serialize.jinja2
RENAMED
File without changes
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/cpp/src/property_structs.cpp.jinja2
RENAMED
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
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/interface_types.py.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/python/method_codes.py.jinja2
RENAMED
File without changes
|
File without changes
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/Cargo.toml.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/examples/client.rs.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/client/src/lib.rs.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/Cargo.toml.jinja2
RENAMED
File without changes
|
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/src/lib.rs.jinja2
RENAMED
File without changes
|
{stinger_ipc-0.0.25 → stinger_ipc-0.0.27}/stingeripc/templates/rust/payloads/src/payloads.rs.jinja2
RENAMED
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|