stinger-ipc 0.0.5__py3-none-any.whl → 0.0.7__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.
Files changed (28) hide show
  1. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/METADATA +2 -2
  2. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/RECORD +27 -23
  3. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/entry_points.txt +1 -0
  4. stingeripc/components.py +5 -5
  5. stingeripc/lang_symb.py +21 -4
  6. stingeripc/templates/html/app.js.jinja2 +117 -0
  7. stingeripc/templates/html/index.html.jinja2 +38 -0
  8. stingeripc/templates/html/style.css.jinja2 +187 -0
  9. stingeripc/templates/rust/Cargo.toml.jinja2 +1 -1
  10. stingeripc/templates/rust/client/Cargo.toml.jinja2 +7 -5
  11. stingeripc/templates/rust/client/examples/client.rs.jinja2 +9 -10
  12. stingeripc/templates/rust/client/src/lib.rs.jinja2 +112 -55
  13. stingeripc/templates/rust/{connection → payloads}/Cargo.toml.jinja2 +8 -4
  14. stingeripc/templates/rust/{connection → payloads}/examples/pub_and_recv.rs.jinja2 +11 -11
  15. stingeripc/templates/rust/payloads/src/lib.rs.jinja2 +4 -0
  16. stingeripc/templates/rust/{connection → payloads}/src/payloads.rs.jinja2 +10 -2
  17. stingeripc/templates/rust/server/Cargo.toml.jinja2 +4 -4
  18. stingeripc/templates/rust/server/examples/server.rs.jinja2 +8 -12
  19. stingeripc/templates/rust/server/src/lib.rs.jinja2 +92 -69
  20. stingeripc/tools/cli.py +73 -0
  21. stingeripc/tools/markdown_generator.py +4 -2
  22. stingeripc/tools/python_generator.py +12 -10
  23. stingeripc/tools/rust_generator.py +46 -27
  24. stingeripc/templates/rust/connection/src/lib.rs.jinja2 +0 -262
  25. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/WHEEL +0 -0
  26. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/licenses/LICENSE +0 -0
  27. {stinger_ipc-0.0.5.dist-info → stinger_ipc-0.0.7.dist-info}/top_level.txt +0 -0
  28. /stingeripc/templates/rust/{connection → payloads}/src/handler.rs.jinja2 +0 -0
@@ -5,20 +5,20 @@ on the next generation.
5
5
  This is the Client for the {{stinger.name}} interface.
6
6
  */
7
7
 
8
- extern crate paho_mqtt as mqtt;
9
- use connection::{MessagePublisher, Connection, ReceivedMessage};
10
-
11
- use json::{JsonValue};
8
+ use mqttier::{MqttierClient, ReceivedMessage};
9
+ {%if stinger.methods|length > 0 -%}
12
10
  use std::collections::HashMap;
11
+ use json::JsonValue;
13
12
  use uuid::Uuid;
13
+ {%endif-%}
14
14
  use serde_json;
15
15
 
16
+
16
17
  #[allow(unused_imports)]
17
- use connection::payloads::{*, MethodResultCode};
18
+ use {{stinger.rust.common_package_name}}::{MethodResultCode, *};
18
19
 
19
20
  use std::sync::{Arc, Mutex};
20
- use tokio::sync::{mpsc, broadcast, oneshot};
21
- use tokio::join;
21
+ use tokio::sync::{broadcast, mpsc{%if stinger.methods|length > 0 -%}, oneshot{%endif-%}};
22
22
  use tokio::task::JoinError;
23
23
 
24
24
  /// This struct is used to store all the MQTTv5 subscription ids
@@ -26,16 +26,19 @@ use tokio::task::JoinError;
26
26
  #[derive(Clone, Debug)]
27
27
  struct {{stinger.name | UpperCamelCase }}SubscriptionIds {
28
28
  {%for method_name, method in stinger.methods.items()-%}
29
- {{method_name | snake_case}}_method_resp: i32,
30
- {%-endfor%}
29
+ {{method_name | snake_case}}_method_resp: usize,
30
+ {%endfor%}
31
31
  {%for sig_name, sig in stinger.signals.items()-%}
32
- {{sig_name | snake_case}}_signal: Option<i32>,
32
+ {{sig_name | snake_case}}_signal: Option<usize>,
33
33
  {%-endfor%}
34
+ {%for prop_name, prop in stinger.properties.items()-%}
35
+ {{prop_name | snake_case}}_property_value: usize,
36
+ {%endfor%}
34
37
  }
35
38
 
36
39
  /// This struct holds the tx side of a broadcast channels used when receiving signals.
37
40
  /// The rx side of the broadcast channels can be created from the tx side later.
38
- /// When {{stinger.name | UpperCamelCase }}Client gets a message and determines that it
41
+ /// When {{stinger.rust.client_struct_name}} gets a message and determines that it
39
42
  /// is a signal, it will send the signal payload via the tx channel that is in this struct.
40
43
  #[derive(Clone)]
41
44
  struct {{stinger.name | UpperCamelCase }}SignalChannels {
@@ -44,61 +47,90 @@ struct {{stinger.name | UpperCamelCase }}SignalChannels {
44
47
  {%endfor%}
45
48
  }
46
49
 
50
+ {%if stinger.properties | length > 0%}
51
+ #[derive(Clone)]
52
+ pub struct {{stinger.name | UpperCamelCase}}Properties {
53
+ {%for prop_name, prop in stinger.properties.items()-%}
54
+ {%-if prop.arg_list | length > 1%}
55
+ pub {{prop_name | snake_case}}: Arc<Mutex<Option<{{prop.rust_type}}>>>,
56
+ {%-else%}
57
+ pub {{prop_name | snake_case}}: Arc<Mutex<Option<{{prop.arg_list[0].rust_type}}>>>,
58
+ {%endif%}
59
+ {%-endfor%}
60
+ }
61
+ {%endif%}
62
+
47
63
  /// This is the struct for our API client.
48
- pub struct {{stinger.name | UpperCamelCase }}Client {
64
+ #[derive(Clone)]
65
+ pub struct {{stinger.rust.client_struct_name}} {
66
+ mqttier_client: MqttierClient,
49
67
  {%if stinger.methods | length > 0 %}/// Temporarily holds oneshot channels for responses to method calls.
50
- pending_responses: Arc<Mutex<HashMap::<Uuid, oneshot::Sender::<JsonValue>>>>,
68
+ pending_responses: Arc<Mutex<HashMap<Uuid, oneshot::Sender<JsonValue>>>>,
51
69
  {%endif%}
52
70
 
53
71
  /// Temporarily holds the receiver for the MPSC channel. The Receiver will be moved
54
72
  /// to a process loop when it is needed. MQTT messages will be received with this.
55
- msg_streamer_rx: Option<mpsc::Receiver<ReceivedMessage>>,
73
+ msg_streamer_rx: Arc<Mutex<Option<mpsc::Receiver<ReceivedMessage>>>>,
56
74
 
57
75
  /// The Sender side of MQTT messages that are received from the broker. This tx
58
76
  /// side is cloned for each subscription made.
77
+ #[allow(dead_code)]
59
78
  msg_streamer_tx: mpsc::Sender<ReceivedMessage>,
60
-
61
- {%if stinger.methods | length > 0 %}/// Through this MessagePublisher object, we can publish messages to MQTT.
62
- msg_publisher: MessagePublisher,
79
+ {%if stinger.properties|length > 0%}
80
+ /// Struct contains all the properties.
81
+ pub properties: {{stinger.name | UpperCamelCase}}Properties,
63
82
  {%endif%}
64
83
  /// Contains all the MQTTv5 subscription ids.
65
84
  subscription_ids: {{stinger.name | UpperCamelCase }}SubscriptionIds,
66
85
 
67
- {%if stinger.signals | length > 0 %}/// Holds the channels used for sending signals to the application.
86
+ {%-if stinger.signals | length > 0 %}
87
+ /// Holds the channels used for sending signals to the application.
68
88
  signal_channels: {{stinger.name | UpperCamelCase }}SignalChannels,
69
89
  {%endif%}
70
90
  /// Copy of MQTT Client ID
71
- client_id: String,
91
+ pub client_id: String,
72
92
  }
73
93
 
74
- impl {{stinger.name | UpperCamelCase }}Client {
94
+ impl {{stinger.rust.client_struct_name}} {
75
95
 
76
- /// Creates a new {{stinger.name | UpperCamelCase }}Client that uses elements from the provided Connection object.
77
- pub async fn new(connection: &mut Connection) -> Self {
78
- let _ = connection.connect().await.expect("Could not connect to MQTT broker");
96
+ /// Creates a new {{stinger.rust.client_struct_name}} that uses an MqttierClient.
97
+ pub async fn new(connection: &mut MqttierClient) -> Self {
79
98
 
80
- // Create a channel for messages to get from the Connection object to this {{stinger.name | UpperCamelCase }}Client object.
99
+ // Create a channel for messages to get from the Connection object to this {{stinger.rust.client_struct_name}} object.
81
100
  // The Connection object uses a clone of the tx side of the channel.
82
101
  let (message_received_tx, message_received_rx) = mpsc::channel(64);
83
102
 
84
- {%if stinger.methods | length > 0 %}// Create the publisher object.
85
- let publisher = connection.get_publisher();
86
-
87
- // Subscribe to all the topics needed for method responses.
88
- {%endif-%}
89
103
  {%for method_name, method in stinger.methods.items()-%}
90
104
  let topic_{{method_name | snake_case}}_method_resp = format!("{{method.response_topic('{}')}}", connection.client_id);
91
- let subscription_id_{{method_name | snake_case}}_method_resp = connection.subscribe(&topic_{{method_name | snake_case}}_method_resp, message_received_tx.clone()).await;
92
- let subscription_id_{{method_name | snake_case}}_method_resp = subscription_id_{{method_name | snake_case}}_method_resp.unwrap_or_else(|_| -1);
105
+ let subscription_id_{{method_name | snake_case}}_method_resp = connection.subscribe(topic_{{method_name | snake_case}}_method_resp, 2, message_received_tx.clone()).await;
106
+ let subscription_id_{{method_name | snake_case}}_method_resp = subscription_id_{{method_name | snake_case}}_method_resp.unwrap_or_else(|_| usize::MAX);
93
107
  {%endfor%}
94
108
 
95
109
  // Subscribe to all the topics needed for signals.
96
110
  {%for signal_name, signal in stinger.signals.items()-%}
97
- let topic_{{signal_name | snake_case}}_signal = "{{signal.topic}}";
98
- let subscription_id_{{signal_name | snake_case}}_signal = connection.subscribe(&topic_{{signal_name | snake_case}}_signal, message_received_tx.clone()).await;
99
- let subscription_id_{{signal_name | snake_case}}_signal = subscription_id_{{signal_name | snake_case}}_signal.unwrap_or_else(|_| -1);
111
+ let topic_{{signal_name | snake_case}}_signal = "{{signal.topic}}".to_string();
112
+ let subscription_id_{{signal_name | snake_case}}_signal = connection.subscribe(topic_{{signal_name | snake_case}}_signal, 2, message_received_tx.clone()).await;
113
+ let subscription_id_{{signal_name | snake_case}}_signal = subscription_id_{{signal_name | snake_case}}_signal.unwrap_or_else(|_| usize::MAX);
100
114
  {%endfor%}
101
115
 
116
+ // Subscribe to all the topics needed for properties.
117
+ {% for prop_name, prop in stinger.properties.items() %}
118
+ let topic_{{prop_name | snake_case}}_property_value = "{{prop.value_topic}}".to_string();
119
+ let subscription_id_{{prop_name | snake_case}}_property_value = connection.subscribe(topic_{{prop_name | snake_case}}_property_value, 1, message_received_tx.clone()).await;
120
+ let subscription_id_{{prop_name | snake_case}}_property_value = subscription_id_{{prop_name | snake_case}}_property_value.unwrap_or_else(|_| usize::MAX);
121
+ {% endfor %}
122
+
123
+ {%if stinger.properties|length > 0%}
124
+ let property_values = {{stinger.name | UpperCamelCase}}Properties {
125
+ {%-for prop_name, prop in stinger.properties.items()%}
126
+ {%if prop.arg_list | length > 1 -%}
127
+ {{prop_name | snake_case}}: Arc::new(Mutex::new(None)),
128
+ {%else%}
129
+ {{prop_name | snake_case}}: Arc::new(Mutex::new(None)),
130
+ {%-endif%}
131
+ {%-endfor%}
132
+ };
133
+ {%endif%}
102
134
  // Create structure for subscription ids.
103
135
  let sub_ids = {{stinger.name | UpperCamelCase }}SubscriptionIds {
104
136
  {%for method_name, method in stinger.methods.items()-%}
@@ -107,6 +139,9 @@ impl {{stinger.name | UpperCamelCase }}Client {
107
139
  {%-for sig_name, sig in stinger.signals.items()-%}
108
140
  {{sig_name | snake_case}}_signal: Some(subscription_id_{{sig_name | snake_case}}_signal),
109
141
  {%endfor%}
142
+ {%-for prop_name, prop in stinger.properties.items()-%}
143
+ {{prop_name | snake_case}}_property_value: subscription_id_{{prop_name | snake_case}}_property_value,
144
+ {%endfor%}
110
145
  };
111
146
 
112
147
  {%if stinger.signals | length > 0 %}// Create structure for the tx side of broadcast channels for signals.
@@ -116,12 +151,15 @@ impl {{stinger.name | UpperCamelCase }}Client {
116
151
  {%endfor%}
117
152
  };{%endif%}
118
153
 
119
- // Create {{stinger.name | UpperCamelCase }}Client structure.
120
- let inst = {{stinger.name | UpperCamelCase }}Client {
154
+ // Create {{stinger.rust.client_struct_name}} structure.
155
+ let inst = {{stinger.rust.client_struct_name}} {
156
+ mqttier_client: connection.clone(),
121
157
  {%if stinger.methods | length > 0 %}pending_responses: Arc::new(Mutex::new(HashMap::new())),{%endif%}
122
- msg_streamer_rx: Some(message_received_rx),
158
+ msg_streamer_rx: Arc::new(Mutex::new(Some(message_received_rx))),
123
159
  msg_streamer_tx: message_received_tx,
124
- {%if stinger.methods | length > 0 %}msg_publisher: publisher,{%endif%}
160
+ {%if stinger.properties|length > 0 %}
161
+ properties: property_values,
162
+ {%endif%}
125
163
  subscription_ids: sub_ids,
126
164
  {%if stinger.signals | length > 0 %}signal_channels: signal_channels,{%endif%}
127
165
  client_id: connection.client_id.to_string(),
@@ -143,23 +181,24 @@ impl {{stinger.name | UpperCamelCase }}Client {
143
181
  /// and published to the `{{method.topic}}` MQTT topic.
144
182
  ///
145
183
  /// This method awaits on the response to the call before returning.
146
- pub async fn {{method_name|snake_case}}(&mut 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> {
184
+ pub async fn {{method_name|snake_case}}(&mut self{%if method.arg_list | length > 0 %}, {%endif%}{%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> {
147
185
  let correlation_id = Uuid::new_v4();
186
+ let correlation_data = correlation_id.as_bytes().to_vec();
148
187
  let (sender, receiver) = oneshot::channel();
149
188
  {
150
189
  let mut hashmap = self.pending_responses.lock().expect("Mutex was poisoned");
151
190
  hashmap.insert(correlation_id.clone(), sender);
152
191
  }
153
192
 
154
- let data = connection::payloads::{{method_name | UpperCamelCase}}RequestObject {
193
+ let data = {{method_name | UpperCamelCase}}RequestObject {
155
194
  {%-for arg in method.arg_list%}
156
195
  {{arg.name}}: {{arg.name|snake_case}},
157
196
  {%-endfor%}
158
197
  };
159
198
 
160
- let response_topic = format!("{{method.response_topic('{}')}}", self.client_id);
161
- let _ = self.msg_publisher.publish_request_structure("{{method.topic}}".to_string(), &data, response_topic.as_str(), correlation_id).await;
162
- let resp_obj = receiver.await.unwrap();
199
+ let response_topic: String = format!("{{method.response_topic('{}')}}", self.client_id);
200
+ let _ = self.mqttier_client.publish_request("{{method.topic}}".to_string(), &data, response_topic, correlation_data).await;
201
+ let {%if method.return_value_type is false %}_{%endif%}resp_obj = receiver.await.unwrap();
163
202
 
164
203
  {%-if method.return_value_type == 'primitive' %}
165
204
  Ok(resp_obj["{{method.return_value_property_name}}"].as_{{method.return_value_rust_type}}().unwrap())
@@ -201,43 +240,61 @@ impl {{stinger.name | UpperCamelCase }}Client {
201
240
  let oss: oneshot::Sender<JsonValue> = sender;
202
241
  match oss.send(payload_object) {
203
242
  Ok(_) => (),
204
- Err(_) => ()
243
+ Err(_) => (),
205
244
  }
206
- },
207
- None => ()
245
+ }
246
+ None => (),
208
247
  }
209
248
  }
210
249
  }
211
250
  {%endfor%}
212
251
 
213
252
  /// Starts the tasks that process messages received.
214
- pub async fn receive_loop(&mut self) -> Result<(), JoinError> {
253
+ pub async fn run_loop(&self) -> Result<(), JoinError> {
254
+ // Make sure the MqttierClient is connected and running.
255
+ let _ = self.mqttier_client.run_loop().await;
256
+
215
257
  {%if stinger.methods | length > 0%}// Clone the Arc pointer to the map. This will be moved into the loop_task.
216
258
  let resp_map: Arc<Mutex<HashMap::<Uuid, oneshot::Sender::<JsonValue>>>> = self.pending_responses.clone();
217
259
  {%endif%}
218
260
  // Take ownership of the RX channel that receives MQTT messages. This will be moved into the loop_task.
219
- let mut message_receiver = self.msg_streamer_rx.take().expect("msg_streamer_rx should be Some");
261
+ let mut message_receiver = {
262
+ let mut guard = self.msg_streamer_rx.lock().expect("Mutex was poisoned");
263
+ guard.take().expect("msg_streamer_rx should be Some")
264
+ };
220
265
 
221
266
  let sig_chans = self.signal_channels.clone();
222
267
  let sub_ids = self.subscription_ids.clone();
223
-
224
- let loop_task = tokio::spawn(async move {
268
+ {%-if stinger.properties|length > 0%}
269
+ let props = self.properties.clone();
270
+ {%endif%}
271
+ let _loop_task = tokio::spawn(async move {
225
272
  while let Some(msg) = message_receiver.recv().await {
226
- let msg_props = msg.message.properties();
227
- let opt_corr_id_bin: Option<Vec<u8>> = msg_props.get_binary(mqtt::PropertyCode::CorrelationData);
228
- let corr_id: Option<Uuid> = opt_corr_id_bin.and_then(|b| Uuid::from_slice(&b).ok());
273
+ {% if stinger.methods|length > 0 %}
274
+ let opt_corr_data: Option<Vec<u8>> = msg.correlation_data.clone();
275
+ let opt_corr_id: Option<Uuid> = opt_corr_data.and_then(|b| Uuid::from_slice(b.as_slice()).ok());
276
+
277
+ let payload = String::from_utf8_lossy(&msg.payload).to_string();
229
278
  {%-for method_name, method in stinger.methods.items()%}
230
279
  {%if not loop.first%}else {%endif%}if msg.subscription_id == sub_ids.{{method_name | snake_case}}_method_resp {
231
- {{stinger.name | UpperCamelCase }}Client::handle_{{method_name|snake_case}}_response(resp_map.clone(), msg.message.payload_str().to_string(), corr_id);
280
+ {{stinger.rust.client_struct_name}}::handle_{{method_name|snake_case}}_response(resp_map.clone(), payload, opt_corr_id);
232
281
  }
233
282
  {%-endfor%}
283
+ {%endif%}
234
284
  {%-for signal_name, signal in stinger.signals.items()%}
235
285
  {%if not loop.first%}else {%endif%}if msg.subscription_id == sub_ids.{{signal_name | snake_case}}_signal.unwrap_or_default() {
236
286
  let chan = sig_chans.{{signal_name | snake_case}}_sender.clone();
237
- let pl: connection::payloads::{{signal_name | UpperCamelCase}}SignalPayload = serde_json::from_str(&msg.message.payload_str()).expect("Failed to deserialize");
287
+ let pl: {{signal_name | UpperCamelCase}}SignalPayload = serde_json::from_slice(&msg.payload).expect("Failed to deserialize");
238
288
  let _send_result = chan.send(pl);
239
289
  }
240
290
  {%endfor%}
291
+ {%-for prop_name, prop in stinger.properties.items()%}
292
+ {%if not loop.first%}else {%endif%}if msg.subscription_id == sub_ids.{{prop_name | snake_case}}_property_value {
293
+ let pl: {{prop.rust_type}} = serde_json::from_slice(&msg.payload).expect("Failed to deserialize");
294
+ let mut guard = props.{{prop_name | snake_case}}.lock().expect("Mutex was poisoned");
295
+ *guard = Some(pl);
296
+ }
297
+ {%endfor%}
241
298
  }
242
299
  });
243
300
 
@@ -1,11 +1,11 @@
1
1
  [package]
2
- name = "connection"
3
- version = "0.1.0"
2
+ name = "{{stinger.rust.common_package_name}}"
3
+ version = "{{stinger.version}}"
4
4
  edition = "2024"
5
5
 
6
6
  [dependencies]
7
7
  futures = "0.3.31"
8
- paho-mqtt = "0.13.3"
8
+ mqttier = { git = "https://github.com/stinger-ipc/mqttier.git" }
9
9
  serde = { version = "1.0.219", features = ["derive"] }
10
10
  serde_json = "1.0.142"
11
11
  tokio = { version = "1", features = ["full"] }
@@ -18,4 +18,8 @@ features = [
18
18
  "v4", # Lets you generate random UUIDs
19
19
  "fast-rng", # Use a faster (but still sufficiently random) RNG
20
20
  "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
21
- ]
21
+ ]
22
+
23
+ [[example]]
24
+ name = "{{stinger.name | snake_case}}_connection_demo"
25
+ path = "examples/pub_and_recv.rs"
@@ -1,5 +1,5 @@
1
1
 
2
- use connection::Connection;
2
+ use mqttier::MqttierClient;
3
3
  use tokio::time::{sleep, Duration};
4
4
  use tokio::join;
5
5
  use tokio::sync::mpsc;
@@ -7,26 +7,26 @@ use tokio::sync::mpsc;
7
7
  #[tokio::main]
8
8
  async fn main() {
9
9
  {%set broker = stinger.get_example_broker()%}
10
- let mut connection = Connection::new_{{broker.class_name|snake_case}}().await.expect("Failed to create connection");
10
+ println!("Starting pub and recv example");
11
+ let client = MqttierClient::new("localhost", 1883, None).unwrap();
11
12
  let (recv_chan_tx, mut recv_chan_rx) = mpsc::channel(32);
12
- connection.connect().await.expect("Failed to connect to broker");
13
- connection.subscribe("example/recv_topic", recv_chan_tx.clone()).await.expect("Failed to subscribe to topic");
14
- let mut publisher = connection.get_publisher();
13
+ client.subscribe("example/recv_topic".to_string(), 1, recv_chan_tx.clone()).await.expect("Failed to subscribe to topic");
15
14
 
16
- let loop_task = tokio::spawn(async move {
17
- connection.start_loop().await;
18
- });
15
+ println!("Starting MQTT client loop");
16
+ client.run_loop().await.unwrap();
19
17
 
18
+ let client2 = client.clone();
20
19
  let _pub_task = tokio::spawn(async move {
21
20
  let mut i = 0;
22
21
  loop {
23
22
  i = i + 1;
24
23
  sleep(Duration::from_secs(1)).await; // Simulate periodic publishing
25
- publisher.publish_simple("example/pub_topic".to_string(), format!("Periodic message {}",i).to_string()).await.expect("Failed to publish periodic message");
24
+ let message = format!("Periodic message {}", i);
25
+ client2.publish_string("example/pub_topic".to_string(), message, 1, false, None).await.expect("Failed to publish periodic message");
26
26
  }
27
27
  });
28
28
 
29
- let _receive_task = tokio::spawn(async move {
29
+ let receive_task = tokio::spawn(async move {
30
30
  loop {
31
31
  match recv_chan_rx.recv().await {
32
32
  Some(message) => {
@@ -40,5 +40,5 @@ async fn main() {
40
40
  }
41
41
  });
42
42
 
43
- let _result = join!(loop_task);
43
+ let _result = join!(receive_task);
44
44
  }
@@ -0,0 +1,4 @@
1
+ pub mod payloads;
2
+
3
+ // Re-export all public types from payloads
4
+ pub use payloads::{*};
@@ -8,7 +8,7 @@ It contains enumerations used by the {{stinger.name}} interface.
8
8
  {%if stinger.enums | length > 0%}
9
9
  use std::fmt;
10
10
  use num_derive::{FromPrimitive, ToPrimitive};
11
- use num_traits::{FromPrimitive, ToPrimitive};
11
+ use num_traits::FromPrimitive;
12
12
  {%endif%}
13
13
  use serde::{Serialize, Deserialize};
14
14
 
@@ -74,6 +74,7 @@ pub enum MethodResultCode { {%-for rc_i, rc_name in stinger.method_return_codes.
74
74
 
75
75
  #[allow(dead_code, non_snake_case)]
76
76
  #[derive(Clone, Debug, Serialize, Deserialize)]
77
+ /// Request Object for `{{method_name}}`
77
78
  pub struct {{method_name | UpperCamelCase}}RequestObject {
78
79
  {%-for arg in method.arg_list%}
79
80
  {%-if arg.arg_type.name.lower() == 'primitive'%}
@@ -83,9 +84,11 @@ pub struct {{method_name | UpperCamelCase}}RequestObject {
83
84
  {%endif-%}
84
85
  {%endfor%}
85
86
  }
86
- {%if method.return_value_type == 'struct'%}
87
+
88
+ {%if method.return_value_type == 'struct' %}
87
89
  #[allow(dead_code)]
88
90
  #[derive(Debug, Clone, Serialize, Deserialize)]
91
+ /// Return Object for `{{method_name}}`
89
92
  pub struct {{method.return_value_name | UpperCamelCase}} {
90
93
  {%-for arg in method.return_value %}
91
94
  pub {{arg.name}}: {{arg.rust_local_type}},
@@ -96,6 +99,11 @@ pub struct {{method.return_value_name | UpperCamelCase}} {
96
99
  pub struct {{method.return_value_name | UpperCamelCase}} {
97
100
  pub {{method.return_value_property_name}}: {{method.return_value.rust_local_type}},
98
101
  }
102
+ {%else%}
103
+ #[derive(Debug, Clone, Serialize)]
104
+ /// Empty (no parameters) return structure for the `{{method_name}}` method.
105
+ pub struct {{method.return_value_name | UpperCamelCase}} {
106
+ }
99
107
  {%endif-%}
100
108
  {%-endfor%}
101
109
  {%for sig_name, sig in stinger.signals.items()%}
@@ -1,13 +1,13 @@
1
1
  [package]
2
- name = "{{stinger.name | snake_case}}_server"
2
+ name = "{{stinger.rust.server_package_name}}"
3
3
  version = "{{stinger.version}}"
4
4
  edition = "2024"
5
5
 
6
6
  [dependencies]
7
- connection = { path = "../connection" }
7
+ {{stinger.rust.common_package_name}} = { path = "../payloads" }
8
8
  futures = "0.3"
9
9
  json = "0.12.4"
10
- paho-mqtt = "0.13.3"
10
+ mqttier = { git = "https://github.com/stinger-ipc/mqttier.git" }
11
11
  num-derive = "0.4.2"
12
12
  num-traits = "0.2.19"
13
13
  tokio = { version = "1", features = ["full"] }
@@ -15,5 +15,5 @@ serde = { version = "1.0.219", features = ["derive"] }
15
15
  serde_json = "1.0.142"
16
16
 
17
17
  [[example]]
18
- name = "{{stinger.name | snake_case}}_server_example"
18
+ name = "{{stinger.name | snake_case}}_server_demo"
19
19
  path = "examples/server.rs"
@@ -5,11 +5,12 @@ on the next generation.
5
5
  It contains enumerations used by the {{stinger.name}} interface.
6
6
  */
7
7
  use futures::{executor::block_on};
8
- use {{stinger.name | snake_case}}_server::{{stinger.rust.server_struct_name}};
9
- use connection::Connection;
8
+ use mqttier::MqttierClient;
9
+ use {{stinger.rust.server_package_name}}::{{stinger.rust.server_struct_name}};
10
10
  use tokio::time::{sleep, Duration};
11
- use tokio::join;
12
- use connection::payloads::{MethodResultCode, *};
11
+
12
+ #[allow(unused_imports)]
13
+ use {{stinger.rust.common_package_name}}::payloads::{MethodResultCode, *};
13
14
 
14
15
  {%for method_name, method in stinger.methods.items()%}
15
16
  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> {
@@ -34,13 +35,9 @@ fn {{method_name|snake_case}}_handler({%for arg in method.arg_list%}_{{arg.name|
34
35
  async fn main() {
35
36
  block_on(async {
36
37
  {%set broker = stinger.get_example_broker()%}
37
- let mut connection = Connection::new_{{broker.class_name|snake_case}}().await.unwrap();
38
+ let mut connection = MqttierClient::new("localhost", 1883, None).unwrap();
38
39
  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
- });
40
+
44
41
  {%for prop_name, prop in stinger.properties.items()%}
45
42
  println!("Setting initial value for property '{{prop_name}}'");
46
43
  {%-if prop.arg_list | length == 1 %}
@@ -76,8 +73,7 @@ async fn main() {
76
73
  server.set_{{prop_name | snake_case}}(new_value).await;
77
74
  {%endif%}
78
75
  {%endfor%}{# property initialization -#}
79
- server.receive_loop().await;
80
- join!(loop_task);
76
+ let _server_loop_task = server.receive_loop().await;
81
77
  });
82
78
  // Ctrl-C to stop
83
79
  }