stinger-ipc 0.0.1__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stinger_ipc-0.0.1.dist-info → stinger_ipc-0.0.3.dist-info}/METADATA +4 -4
- stinger_ipc-0.0.3.dist-info/RECORD +52 -0
- stinger_ipc-0.0.3.dist-info/entry_points.txt +4 -0
- stingeripc/args.py +6 -5
- stingeripc/asyncapi.py +249 -167
- stingeripc/components.py +301 -136
- stingeripc/connection.py +2 -1
- stingeripc/exceptions.py +1 -2
- stingeripc/interface.py +8 -4
- stingeripc/lang_symb.py +68 -0
- stingeripc/templates/cpp/CMakeLists.txt.jinja2 +26 -0
- stingeripc/templates/cpp/examples/client_main.cpp.jinja2 +47 -0
- stingeripc/templates/cpp/examples/server_main.cpp.jinja2 +35 -0
- stingeripc/templates/cpp/include/broker.hpp.jinja2 +132 -0
- stingeripc/templates/cpp/include/client.hpp.jinja2 +53 -0
- stingeripc/templates/cpp/include/enums.hpp.jinja2 +17 -0
- stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2 +42 -0
- stingeripc/templates/cpp/include/return_types.hpp.jinja2 +14 -0
- stingeripc/templates/cpp/include/server.hpp.jinja2 +44 -0
- stingeripc/templates/cpp/include/structs.hpp.jinja2 +13 -0
- stingeripc/templates/cpp/src/broker.cpp.jinja2 +243 -0
- stingeripc/templates/cpp/src/client.cpp.jinja2 +202 -0
- stingeripc/templates/cpp/src/server.cpp.jinja2 +170 -0
- stingeripc/templates/markdown/index.md.jinja2 +142 -0
- stingeripc/templates/python/__init__.py.jinja2 +1 -0
- stingeripc/templates/python/client.py.jinja2 +309 -0
- stingeripc/templates/python/connection.py.jinja2 +164 -0
- stingeripc/templates/python/interface_types.py.jinja2 +48 -0
- stingeripc/templates/python/method_codes.py.jinja2 +30 -0
- stingeripc/templates/python/pyproject.toml.jinja2 +9 -0
- stingeripc/templates/python/server.py.jinja2 +214 -0
- stingeripc/templates/rust/Cargo.toml.jinja2 +4 -0
- stingeripc/templates/rust/client/Cargo.toml.jinja2 +25 -0
- stingeripc/templates/rust/client/examples/client.rs.jinja2 +53 -0
- stingeripc/templates/rust/client/src/lib.rs.jinja2 +247 -0
- stingeripc/templates/rust/connection/Cargo.toml.jinja2 +21 -0
- stingeripc/templates/rust/connection/examples/pub_and_recv.rs.jinja2 +44 -0
- stingeripc/templates/rust/connection/src/handler.rs.jinja2 +0 -0
- stingeripc/templates/rust/connection/src/lib.rs.jinja2 +262 -0
- stingeripc/templates/rust/connection/src/payloads.rs.jinja2 +131 -0
- stingeripc/templates/rust/server/Cargo.toml.jinja2 +19 -0
- stingeripc/templates/rust/server/examples/server.rs.jinja2 +83 -0
- stingeripc/templates/rust/server/src/lib.rs.jinja2 +272 -0
- stingeripc/tools/__init__.py +0 -0
- stingeripc/tools/markdown_generator.py +25 -0
- stingeripc/tools/python_generator.py +41 -0
- stingeripc/tools/rust_generator.py +50 -0
- stingeripc/topic.py +11 -8
- stinger_ipc-0.0.1.dist-info/RECORD +0 -13
- {stinger_ipc-0.0.1.dist-info → stinger_ipc-0.0.3.dist-info}/WHEEL +0 -0
- {stinger_ipc-0.0.1.dist-info → stinger_ipc-0.0.3.dist-info}/licenses/LICENSE +0 -0
- {stinger_ipc-0.0.1.dist-info → stinger_ipc-0.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,262 @@
|
|
1
|
+
|
2
|
+
pub mod payloads;
|
3
|
+
|
4
|
+
extern crate paho_mqtt as mqtt;
|
5
|
+
use uuid::Uuid;
|
6
|
+
use futures::{StreamExt};
|
7
|
+
use mqtt::{Message, QOS_1, QOS_2};
|
8
|
+
use std::collections::HashMap;
|
9
|
+
use tokio::sync::mpsc::{self, Sender, Receiver};
|
10
|
+
use tokio::sync::mpsc::error::SendError;
|
11
|
+
use std::time::Duration;
|
12
|
+
use std::sync::{Arc, Mutex};
|
13
|
+
use serde::Serialize;
|
14
|
+
use serde_json::{self};
|
15
|
+
|
16
|
+
#[derive(Clone, Debug)]
|
17
|
+
pub struct ReceivedMessage {
|
18
|
+
pub message: mqtt::Message,
|
19
|
+
pub subscription_id: i32,
|
20
|
+
}
|
21
|
+
|
22
|
+
#[derive(Clone)]
|
23
|
+
pub struct MessageStreamer {
|
24
|
+
pub subscriptions: Arc<Mutex<HashMap<i32, Sender<ReceivedMessage>>>>,
|
25
|
+
pub strm: mqtt::AsyncReceiver<Option<mqtt::Message>>
|
26
|
+
}
|
27
|
+
|
28
|
+
impl MessageStreamer {
|
29
|
+
pub async fn receive_loop(&mut self) -> Result<(), paho_mqtt::Error> {
|
30
|
+
println!("Starting message receive loop...");
|
31
|
+
while let Some(msg_opt) = self.strm.next().await {
|
32
|
+
if let Some(msg) = msg_opt {
|
33
|
+
let mut sub_id_itr = msg.properties().iter(mqtt::PropertyCode::SubscriptionIdentifier);
|
34
|
+
while let Some(sub_id_prop) = sub_id_itr.next() {
|
35
|
+
let opt_sub_id = sub_id_prop.get_int();
|
36
|
+
if let Some(sub_id) = opt_sub_id {
|
37
|
+
if let Some(tx) = self.subscriptions.lock().unwrap().get(&sub_id) {
|
38
|
+
let tx2 = tx.clone();
|
39
|
+
let received_msg = ReceivedMessage {
|
40
|
+
message: msg.clone(),
|
41
|
+
subscription_id: sub_id,
|
42
|
+
};
|
43
|
+
tokio::spawn(async move {
|
44
|
+
if let Err(e) = tx2.send(received_msg).await {
|
45
|
+
eprintln!("Failed to send message: {}", e);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
} else {
|
49
|
+
println!("No subscription found for ID: {}", sub_id);
|
50
|
+
}
|
51
|
+
} else {
|
52
|
+
println!("No subscription ID found in message properties.");
|
53
|
+
}
|
54
|
+
}
|
55
|
+
} else {
|
56
|
+
println!("Received None, stream closed.");
|
57
|
+
}
|
58
|
+
|
59
|
+
}
|
60
|
+
Ok(())
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
#[derive(Clone)]
|
65
|
+
pub struct MessagePublisher {
|
66
|
+
pub channel: Sender<mqtt::Message>
|
67
|
+
}
|
68
|
+
|
69
|
+
impl MessagePublisher {
|
70
|
+
pub async fn publish(&mut self, msg: mqtt::Message) -> Result<(), SendError<Message>> {
|
71
|
+
println!("Message publisher publishing message to {}", msg.topic());
|
72
|
+
self.channel.send(msg).await
|
73
|
+
}
|
74
|
+
|
75
|
+
pub async fn publish_simple(&mut self, topic: String, payload: String) -> Result<(), SendError<Message>> {
|
76
|
+
let msg = mqtt::Message::new(topic, payload, QOS_1);
|
77
|
+
self.publish(msg).await
|
78
|
+
}
|
79
|
+
|
80
|
+
pub async fn publish_structure<T: Serialize>(&mut self, topic: String, data: &T) -> Result<(), SendError<Message>> {
|
81
|
+
let payload = serde_json::to_string(data).unwrap().into_bytes();
|
82
|
+
let mut pub_props = mqtt::Properties::new();
|
83
|
+
let _ = pub_props.push_string(mqtt::PropertyCode::ContentType, "application/json");
|
84
|
+
let msg = mqtt::MessageBuilder::new()
|
85
|
+
.topic(topic)
|
86
|
+
.payload(payload)
|
87
|
+
.properties(pub_props)
|
88
|
+
.qos(QOS_1)
|
89
|
+
.finalize();
|
90
|
+
self.publish(msg).await
|
91
|
+
}
|
92
|
+
|
93
|
+
pub async fn publish_retained_structure<T: Serialize>(&mut self, topic: String, data: &T) -> Result<(), SendError<Message>> {
|
94
|
+
let payload = serde_json::to_string(data).unwrap().into_bytes();
|
95
|
+
let mut pub_props = mqtt::Properties::new();
|
96
|
+
let _ = pub_props.push_string(mqtt::PropertyCode::ContentType, "application/json");
|
97
|
+
let msg = mqtt::MessageBuilder::new()
|
98
|
+
.topic(topic)
|
99
|
+
.payload(payload)
|
100
|
+
.properties(pub_props)
|
101
|
+
.qos(QOS_1)
|
102
|
+
.retained(true)
|
103
|
+
.finalize();
|
104
|
+
self.publish(msg).await
|
105
|
+
}
|
106
|
+
|
107
|
+
pub async fn publish_request_structure<T: Serialize>(&mut self, topic: String, data: &T, response_topic: &str, correlation_id: Uuid) -> Result<(), SendError<Message>> {
|
108
|
+
println!("Publishing request structure to {} with responses going to {}", topic, response_topic);
|
109
|
+
let uuid_vec: Vec<u8> = correlation_id.as_bytes().to_vec();
|
110
|
+
let mut pub_props = mqtt::Properties::new();
|
111
|
+
let _ = pub_props.push_binary(mqtt::PropertyCode::CorrelationData, uuid_vec);
|
112
|
+
let _ = pub_props.push_string(mqtt::PropertyCode::ResponseTopic, response_topic);
|
113
|
+
let _ = pub_props.push_string(mqtt::PropertyCode::ContentType, "application/json");
|
114
|
+
let payload = serde_json::to_string(data).unwrap().into_bytes();
|
115
|
+
let msg = mqtt::MessageBuilder::new()
|
116
|
+
.topic(topic)
|
117
|
+
.qos(QOS_2)
|
118
|
+
.properties(pub_props)
|
119
|
+
.payload(payload)
|
120
|
+
.finalize();
|
121
|
+
self.publish(msg).await
|
122
|
+
}
|
123
|
+
|
124
|
+
pub async fn publish_response_structure<T: Serialize>(&mut self, topic: String, data: &T, correlation_id: Option<Vec<u8>>) -> Result<(), SendError<Message>> {
|
125
|
+
let mut pub_props = mqtt::Properties::new();
|
126
|
+
if let Some(corr_id) = correlation_id {
|
127
|
+
let _ = pub_props.push_binary(mqtt::PropertyCode::CorrelationData, corr_id);
|
128
|
+
}
|
129
|
+
let payload = serde_json::to_string(data).unwrap().into_bytes();
|
130
|
+
let _ = pub_props.push_string(mqtt::PropertyCode::ContentType, "application/json");
|
131
|
+
let msg = mqtt::MessageBuilder::new()
|
132
|
+
.topic(topic)
|
133
|
+
.payload(payload)
|
134
|
+
.qos(QOS_2)
|
135
|
+
.properties(pub_props)
|
136
|
+
.finalize();
|
137
|
+
self.publish(msg).await
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
pub struct Connection {
|
142
|
+
pub client: paho_mqtt::AsyncClient,
|
143
|
+
pub client_id: String,
|
144
|
+
pub next_subscription_id: i32,
|
145
|
+
pub subscriptions: Arc<Mutex<HashMap<i32, Sender<ReceivedMessage>>>>,
|
146
|
+
pub pub_chan_rx: Receiver<mqtt::Message>,
|
147
|
+
pub pub_chan_tx: Sender<mqtt::Message>,
|
148
|
+
}
|
149
|
+
|
150
|
+
impl Connection {
|
151
|
+
pub async fn new(broker: &str) -> Result<Self, paho_mqtt::Error> {
|
152
|
+
println!("Creating new connection object");
|
153
|
+
let client_id_uuid = Uuid::new_v4();
|
154
|
+
let client_id = client_id_uuid.to_string();
|
155
|
+
let create_opts = mqtt::CreateOptionsBuilder::new()
|
156
|
+
.server_uri(broker)
|
157
|
+
.mqtt_version(mqtt::MQTT_VERSION_5)
|
158
|
+
.allow_disconnected_send_at_anytime(true)
|
159
|
+
.client_id(client_id.clone())
|
160
|
+
.finalize();
|
161
|
+
let (tx, rx) = mpsc::channel(32);
|
162
|
+
let client = paho_mqtt::AsyncClient::new(create_opts)?;
|
163
|
+
Ok(Self {
|
164
|
+
client,
|
165
|
+
client_id,
|
166
|
+
next_subscription_id: 5,
|
167
|
+
subscriptions: Arc::new(Mutex::new(HashMap::new())),
|
168
|
+
pub_chan_rx: rx,
|
169
|
+
pub_chan_tx: tx,
|
170
|
+
})
|
171
|
+
}
|
172
|
+
|
173
|
+
{%for broker_name, broker in stinger.brokers.items()%}
|
174
|
+
pub async fn new_{{broker.class_name | snake_case}}() -> Result<Self, paho_mqtt::Error> {
|
175
|
+
Connection::new("{{broker.hostname or 'localhost'}}:{{broker.port or 1883}}").await
|
176
|
+
}
|
177
|
+
{%endfor%}
|
178
|
+
|
179
|
+
fn get_subscription_id(&mut self) -> i32 {
|
180
|
+
let id = self.next_subscription_id;
|
181
|
+
self.next_subscription_id += 1;
|
182
|
+
id
|
183
|
+
}
|
184
|
+
|
185
|
+
pub async fn get_streamer(&mut self) -> MessageStreamer {
|
186
|
+
let strm = self.client.get_stream(25);
|
187
|
+
MessageStreamer {
|
188
|
+
subscriptions: self.subscriptions.clone(),
|
189
|
+
strm,
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
pub fn get_publisher(&self) -> MessagePublisher {
|
194
|
+
let channel = self.pub_chan_tx.clone();
|
195
|
+
MessagePublisher {
|
196
|
+
channel,
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
pub async fn connect(&self) -> Result<paho_mqtt::ServerResponse, paho_mqtt::Error> {
|
201
|
+
println!("Connecting to mqtt");
|
202
|
+
let conn_opts = mqtt::ConnectOptionsBuilder::new_v5()
|
203
|
+
.keep_alive_interval(Duration::from_secs(20))
|
204
|
+
.clean_start(true)
|
205
|
+
.finalize();
|
206
|
+
|
207
|
+
self.client.connect(conn_opts).await
|
208
|
+
}
|
209
|
+
|
210
|
+
pub async fn disconnect(&self) -> Result<paho_mqtt::ServerResponse, paho_mqtt::Error> {
|
211
|
+
self.client.disconnect(None).await
|
212
|
+
}
|
213
|
+
|
214
|
+
pub async fn publish(&self, msg: mqtt::Message) -> Result<(), paho_mqtt::Error> {
|
215
|
+
println!("Publishing message to {}", msg.topic());
|
216
|
+
let pub_result = self.client.publish(msg).await;
|
217
|
+
pub_result
|
218
|
+
}
|
219
|
+
|
220
|
+
async fn add_subscription_receiver(
|
221
|
+
&mut self,
|
222
|
+
subscription_id: i32,
|
223
|
+
tx: Sender<ReceivedMessage>,
|
224
|
+
) -> Result<(), paho_mqtt::Error> {
|
225
|
+
let mut subscriptions = self.subscriptions.lock().unwrap();
|
226
|
+
subscriptions.insert(subscription_id, tx);
|
227
|
+
Ok(())
|
228
|
+
}
|
229
|
+
|
230
|
+
pub async fn subscribe(&mut self, topic: &str, tx: Sender<ReceivedMessage>) -> Result<i32, paho_mqtt::Error> {
|
231
|
+
println!("Subscribing to {}", topic);
|
232
|
+
let sub_opts = mqtt::SubscribeOptions::new(true, false, mqtt::RetainHandling::SendRetainedOnSubscribe);
|
233
|
+
let mut sub_props = mqtt::Properties::new();
|
234
|
+
let subscription_id = self.get_subscription_id();
|
235
|
+
let si_prop = mqtt::Property::new(mqtt::PropertyCode::SubscriptionIdentifier, subscription_id as i32).unwrap();
|
236
|
+
let _ = sub_props.push(si_prop);
|
237
|
+
let _sub_result = self.client.subscribe_with_options(topic, paho_mqtt::QOS_1, sub_opts, sub_props).await;
|
238
|
+
self.add_subscription_receiver(subscription_id, tx).await?;
|
239
|
+
Ok(subscription_id)
|
240
|
+
}
|
241
|
+
|
242
|
+
pub async fn start_loop(&mut self) {
|
243
|
+
println!("Starting MQTT loop...");
|
244
|
+
|
245
|
+
let mut streamer = self.get_streamer().await;
|
246
|
+
let _stream_task = tokio::spawn(async move {
|
247
|
+
let _ = streamer.receive_loop().await;
|
248
|
+
});
|
249
|
+
|
250
|
+
loop {
|
251
|
+
let opt_msg = self.pub_chan_rx.recv().await;
|
252
|
+
if let Some(msg) = opt_msg {
|
253
|
+
let pub_result = self.publish(msg).await;
|
254
|
+
match pub_result {
|
255
|
+
Ok(_r) => println!("Message was published"),
|
256
|
+
Err(e) => eprintln!("Error publishing: {:?}", e),
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
262
|
+
}
|
@@ -0,0 +1,131 @@
|
|
1
|
+
/*
|
2
|
+
DO NOT MODIFY THIS FILE {# unless you see this comment #}. It is automatically generated and changes will be over-written
|
3
|
+
on the next generation.
|
4
|
+
|
5
|
+
It contains enumerations used by the {{stinger.name}} interface.
|
6
|
+
*/
|
7
|
+
|
8
|
+
{%if stinger.enums | length > 0%}
|
9
|
+
use std::fmt;
|
10
|
+
use num_derive::{FromPrimitive, ToPrimitive};
|
11
|
+
use num_traits::{FromPrimitive, ToPrimitive};
|
12
|
+
{%endif%}
|
13
|
+
use serde::{Serialize, Deserialize};
|
14
|
+
|
15
|
+
{%for ie_name, ie in stinger.enums.items() %}
|
16
|
+
#[repr(u32)]
|
17
|
+
#[derive(Debug, FromPrimitive, ToPrimitive, Clone, Serialize, Deserialize)]
|
18
|
+
#[serde(into = "u32", try_from = "u32")]
|
19
|
+
pub enum {{ie_name | UpperCamelCase }} {
|
20
|
+
{%-for value in ie.values %}
|
21
|
+
{{value | UpperCamelCase}} = {{loop.index}}{%if not loop.last%},{%endif%}
|
22
|
+
{%-endfor%}
|
23
|
+
}
|
24
|
+
|
25
|
+
#[allow(dead_code)]
|
26
|
+
impl {{ie_name | UpperCamelCase }} {
|
27
|
+
pub fn from_u32(value: u32) -> Option<Self> {
|
28
|
+
FromPrimitive::from_u32(value)
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
impl From<{{ie_name | UpperCamelCase }}> for u32 {
|
33
|
+
fn from(s: {{ie_name | UpperCamelCase }}) -> u32 {
|
34
|
+
s as u32
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
impl From<u32> for {{ie_name | UpperCamelCase }} {
|
39
|
+
fn from(s: u32) -> {{ie_name | UpperCamelCase }} {
|
40
|
+
{{ie_name | UpperCamelCase }}::from_u32(s).unwrap()
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
impl fmt::Display for {{ie_name | UpperCamelCase }} {
|
45
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
46
|
+
write!(f, "{:?}", self)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
{%endfor%}
|
50
|
+
|
51
|
+
{%for struct_name, struct in stinger.structs.items() %}
|
52
|
+
#[allow(dead_code, non_snake_case)]
|
53
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
54
|
+
pub struct {{struct_name | UpperCamelCase}} {
|
55
|
+
{%-for arg in struct.members%}
|
56
|
+
{%-if arg.arg_type.name.lower() == 'primitive'%}
|
57
|
+
pub {{arg.name}}: {{arg.rust_type}},
|
58
|
+
{%-elif arg.arg_type.name.lower() == 'enum'%}
|
59
|
+
pub {{arg.name}}: {{arg.rust_local_type}},
|
60
|
+
{%endif-%}
|
61
|
+
{%endfor%}
|
62
|
+
}
|
63
|
+
{%-endfor%}
|
64
|
+
|
65
|
+
#[allow(dead_code)]
|
66
|
+
#[derive(Debug)]
|
67
|
+
pub enum MethodResultCode { {%-for rc_i, rc_name in stinger.method_return_codes.items()%}
|
68
|
+
{{rc_name | UpperCamelCase}} = {{rc_i}},
|
69
|
+
{%-endfor%}
|
70
|
+
}
|
71
|
+
|
72
|
+
{%for method_name, method in stinger.methods.items()%}
|
73
|
+
// Structures for `{{method_name}}` method
|
74
|
+
|
75
|
+
#[allow(dead_code, non_snake_case)]
|
76
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
77
|
+
pub struct {{method_name | UpperCamelCase}}RequestObject {
|
78
|
+
{%-for arg in method.arg_list%}
|
79
|
+
{%-if arg.arg_type.name.lower() == 'primitive'%}
|
80
|
+
pub {{arg.name}}: {{arg.rust_type}},
|
81
|
+
{%-elif arg.arg_type.name.lower() == 'enum'-%}
|
82
|
+
pub {{arg.name}}: u32,
|
83
|
+
{%endif-%}
|
84
|
+
{%endfor%}
|
85
|
+
}
|
86
|
+
{%if method.return_value_type == 'struct'%}
|
87
|
+
#[allow(dead_code)]
|
88
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
89
|
+
pub struct {{method.return_value_name | UpperCamelCase}} {
|
90
|
+
{%-for arg in method.return_value %}
|
91
|
+
pub {{arg.name}}: {{arg.rust_local_type}},
|
92
|
+
{%-endfor%}
|
93
|
+
}
|
94
|
+
{%elif method.return_value_type == 'primitive'%}
|
95
|
+
#[derive(Debug, Clone, Serialize)]
|
96
|
+
pub struct {{method.return_value_name | UpperCamelCase}} {
|
97
|
+
pub {{method.return_value_property_name}}: {{method.return_value.rust_local_type}},
|
98
|
+
}
|
99
|
+
{%endif-%}
|
100
|
+
{%-endfor%}
|
101
|
+
{%for sig_name, sig in stinger.signals.items()%}
|
102
|
+
// Structures for `{{sig_name}}` signal
|
103
|
+
#[allow(dead_code, non_snake_case)]
|
104
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
105
|
+
pub struct {{sig_name | UpperCamelCase}}SignalPayload {
|
106
|
+
{%-for arg in sig.arg_list%}
|
107
|
+
{%-if arg.arg_type.name.lower() == 'primitive'%}
|
108
|
+
pub {{arg.name}}: {{arg.rust_type}},
|
109
|
+
{%elif arg.arg_type.name.lower() == 'enum'-%}
|
110
|
+
pub {{arg.name}}: {{arg.rust_local_type}},
|
111
|
+
{%endif-%}
|
112
|
+
{%endfor%}
|
113
|
+
}
|
114
|
+
{%endfor%}
|
115
|
+
|
116
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
117
|
+
// `{{prop_name}}` property structure.
|
118
|
+
#[allow(dead_code, non_snake_case)]
|
119
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
120
|
+
pub struct {{prop_name | UpperCamelCase}}Property {
|
121
|
+
{%for arg in prop.arg_list%}
|
122
|
+
{%-if arg.arg_type.name.lower() == 'primitive' -%}
|
123
|
+
pub {{arg.name}}: {{arg.rust_type}},
|
124
|
+
{%elif arg.arg_type.name.lower() == 'enum'-%}
|
125
|
+
pub {{arg.name}}: {{arg.rust_local_type}},
|
126
|
+
{%elif arg.arg_type.name.lower() == 'struct'-%}
|
127
|
+
pub {{arg.name}}: {{arg.rust_local_type}},
|
128
|
+
{%endif-%}
|
129
|
+
{%endfor%}
|
130
|
+
}
|
131
|
+
{%endfor%}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
[package]
|
2
|
+
name = "{{stinger.name | snake_case}}_server"
|
3
|
+
version = "{{stinger.version}}"
|
4
|
+
edition = "2024"
|
5
|
+
|
6
|
+
[dependencies]
|
7
|
+
connection = { path = "../connection" }
|
8
|
+
futures = "0.3"
|
9
|
+
json = "0.12.4"
|
10
|
+
paho-mqtt = "0.13.3"
|
11
|
+
num-derive = "0.4.2"
|
12
|
+
num-traits = "0.2.19"
|
13
|
+
tokio = { version = "1", features = ["full"] }
|
14
|
+
serde = { version = "1.0.219", features = ["derive"] }
|
15
|
+
serde_json = "1.0.142"
|
16
|
+
|
17
|
+
[[example]]
|
18
|
+
name = "{{stinger.name | snake_case}}_server_example"
|
19
|
+
path = "examples/server.rs"
|
@@ -0,0 +1,83 @@
|
|
1
|
+
/*
|
2
|
+
DO NOT MODIFY THIS FILE {# unless you see this comment #}. It is automatically generated and changes will be over-written
|
3
|
+
on the next generation.
|
4
|
+
|
5
|
+
It contains enumerations used by the {{stinger.name}} interface.
|
6
|
+
*/
|
7
|
+
use futures::{executor::block_on};
|
8
|
+
use {{stinger.name | snake_case}}_server::{{stinger.rust.server_struct_name}};
|
9
|
+
use connection::Connection;
|
10
|
+
use tokio::time::{sleep, Duration};
|
11
|
+
use tokio::join;
|
12
|
+
use connection::payloads::{MethodResultCode, *};
|
13
|
+
|
14
|
+
{%for method_name, method in stinger.methods.items()%}
|
15
|
+
fn {{method_name|snake_case}}_handler({%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> {
|
16
|
+
println!("Handling {{method_name}}");
|
17
|
+
{%-if method.return_value_type == 'struct'%}
|
18
|
+
let rv = {{method.return_value_rust_type}} {
|
19
|
+
{%for arg in method.return_value-%}
|
20
|
+
{{arg.name}}: {{arg.get_random_example_value(lang="rust")}},
|
21
|
+
{%endfor%}
|
22
|
+
};
|
23
|
+
Ok(rv)
|
24
|
+
{%elif method.return_value_type is not false %}
|
25
|
+
Ok({{method.return_value.get_random_example_value(lang="rust")}})
|
26
|
+
{%else%}
|
27
|
+
Ok(())
|
28
|
+
{%-endif%}
|
29
|
+
}
|
30
|
+
{%endfor%}
|
31
|
+
|
32
|
+
|
33
|
+
#[tokio::main]
|
34
|
+
async fn main() {
|
35
|
+
block_on(async {
|
36
|
+
{%set broker = stinger.get_example_broker()%}
|
37
|
+
let mut connection = Connection::new_{{broker.class_name|snake_case}}().await.unwrap();
|
38
|
+
let mut server = {{stinger.rust.server_struct_name}}::new(&mut connection).await;
|
39
|
+
|
40
|
+
let loop_task = tokio::spawn(async move {
|
41
|
+
println!("Making call to start connection loop");
|
42
|
+
let _conn_loop = connection.start_loop().await;
|
43
|
+
});
|
44
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
45
|
+
println!("Setting initial value for property '{{prop_name}}'");
|
46
|
+
{%-if prop.arg_list | length == 1 %}
|
47
|
+
server.set_{{prop_name | snake_case}}({{prop.arg_list[0].get_random_example_value(lang="rust")}}).await;
|
48
|
+
{%-else%}{# many args in property #}
|
49
|
+
let new_value = {{prop.rust_type}} {
|
50
|
+
{%-for arg in prop.arg_list %}
|
51
|
+
{{arg.name}}: {{arg.get_random_example_value(lang="rust")}},
|
52
|
+
{%-endfor%}
|
53
|
+
};
|
54
|
+
server.set_{{prop_name | snake_case}}(new_value).await;
|
55
|
+
{%endif%}
|
56
|
+
{%endfor%}{# property initialization -#}
|
57
|
+
{%-for method_name, method in stinger.methods.items()%}
|
58
|
+
server.set_method_handler_for_{{method_name|snake_case}}({{method_name|snake_case}}_handler);
|
59
|
+
{%endfor%}
|
60
|
+
{%for sig_name, sig in stinger.signals.items()%}
|
61
|
+
sleep(Duration::from_secs(1)).await;
|
62
|
+
println!("Emitting signal '{{sig_name}}'");
|
63
|
+
server.emit_{{sig_name|snake_case}}({%for arg in sig.arg_list%}{{arg.get_random_example_value(lang="rust")}}{%if not loop.last%}, {%endif%}{%endfor%}).await;
|
64
|
+
{%endfor%}
|
65
|
+
{%for prop_name, prop in stinger.properties.items()%}
|
66
|
+
sleep(Duration::from_secs(1)).await;
|
67
|
+
println!("Changing property '{{prop_name}}'");
|
68
|
+
{%-if prop.arg_list | length == 1 %}
|
69
|
+
server.set_{{prop_name | snake_case}}({{prop.arg_list[0].get_random_example_value(lang="rust", seed=3)}}).await;
|
70
|
+
{%-else%}{# many args in property #}
|
71
|
+
let new_value = {{prop.rust_type}} {
|
72
|
+
{%-for arg in prop.arg_list %}
|
73
|
+
{{arg.name}}: {{arg.get_random_example_value(lang="rust", seed=4)}},
|
74
|
+
{%-endfor%}
|
75
|
+
};
|
76
|
+
server.set_{{prop_name | snake_case}}(new_value).await;
|
77
|
+
{%endif%}
|
78
|
+
{%endfor%}{# property initialization -#}
|
79
|
+
server.receive_loop().await;
|
80
|
+
join!(loop_task);
|
81
|
+
});
|
82
|
+
// Ctrl-C to stop
|
83
|
+
}
|