stinger-ipc 0.0.9__py3-none-any.whl → 0.0.25__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 (36) hide show
  1. {stinger_ipc-0.0.9.dist-info → stinger_ipc-0.0.25.dist-info}/METADATA +3 -2
  2. stinger_ipc-0.0.25.dist-info/RECORD +63 -0
  3. stingeripc/asyncapi.py +3 -0
  4. stingeripc/components.py +61 -10
  5. stingeripc/schema/schema.yaml +240 -0
  6. stingeripc/templates/cpp/examples/client_main.cpp.jinja2 +18 -0
  7. stingeripc/templates/cpp/include/broker.hpp.jinja2 +18 -10
  8. stingeripc/templates/cpp/include/client.hpp.jinja2 +80 -11
  9. stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2 +24 -4
  10. stingeripc/templates/cpp/include/property_structs.hpp.jinja2 +40 -2
  11. stingeripc/templates/cpp/include/server.hpp.jinja2 +5 -1
  12. stingeripc/templates/cpp/include/structs.hpp.jinja2 +2 -0
  13. stingeripc/templates/cpp/partials/args.jinja2 +11 -0
  14. stingeripc/templates/cpp/partials/deserialize.jinja2 +42 -0
  15. stingeripc/templates/cpp/partials/serialize.jinja2 +18 -0
  16. stingeripc/templates/cpp/src/broker.cpp.jinja2 +46 -24
  17. stingeripc/templates/cpp/src/client.cpp.jinja2 +109 -36
  18. stingeripc/templates/cpp/src/property_structs.cpp.jinja2 +25 -0
  19. stingeripc/templates/cpp/src/server.cpp.jinja2 +17 -25
  20. stingeripc/templates/cpp/src/structs.cpp.jinja2 +13 -0
  21. stingeripc/templates/html/app.js.jinja2 +130 -29
  22. stingeripc/templates/html/index.html.jinja2 +96 -8
  23. stingeripc/templates/html/styles.css.jinja2 +135 -0
  24. stingeripc/templates/markdown/index.md.jinja2 +151 -10
  25. stingeripc/templates/rust/client/src/lib.rs.jinja2 +24 -5
  26. stingeripc/templates/rust/server/examples/server.rs.jinja2 +59 -23
  27. stingeripc/templates/rust/server/src/lib.rs.jinja2 +78 -55
  28. stingeripc/tools/cli.py +33 -7
  29. stingeripc/tools/cpp_generator.py +90 -0
  30. stingeripc/tools/rust_generator.py +1 -1
  31. stinger_ipc-0.0.9.dist-info/RECORD +0 -57
  32. stingeripc/templates/rust/payloads/src/handler.rs.jinja2 +0 -0
  33. {stinger_ipc-0.0.9.dist-info → stinger_ipc-0.0.25.dist-info}/WHEEL +0 -0
  34. {stinger_ipc-0.0.9.dist-info → stinger_ipc-0.0.25.dist-info}/entry_points.txt +0 -0
  35. {stinger_ipc-0.0.9.dist-info → stinger_ipc-0.0.25.dist-info}/licenses/LICENSE +0 -0
  36. {stinger_ipc-0.0.9.dist-info → stinger_ipc-0.0.25.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,7 @@
1
+ {% import "partials/deserialize.jinja2" as deser %}
2
+ {% import "partials/serialize.jinja2" as ser %}
3
+ {% import "partials/args.jinja2" as ar %}
4
+ {%macro prop_value_type(prop) -%}{%if prop.arg_list|length > 1%}struct {%endif%}{{prop.name | UpperCamelCase}}Property{%endmacro%}
1
5
 
2
6
  #include <vector>
3
7
  #include <iostream>
@@ -16,20 +20,22 @@
16
20
  #include "{{stinger.cpp.enum_header_file}}"
17
21
  #include "ibrokerconnection.hpp"
18
22
 
19
-
20
23
  constexpr const char {{stinger.cpp.client_class_name}}::NAME[];
21
24
  constexpr const char {{stinger.cpp.client_class_name}}::INTERFACE_VERSION[];
22
25
 
23
26
  {{stinger.cpp.client_class_name}}::{{stinger.cpp.client_class_name}}(std::shared_ptr<IBrokerConnection> broker) : _broker(broker)
24
27
  {
25
- _broker->AddMessageCallback([this](const std::string& topic, const std::string& payload, const boost::optional<std::string> optCorrelationId, const boost::optional<std::string> unusedRespTopic, const boost::optional<MethodResultCode> optResultCode)
28
+ _broker->AddMessageCallback([this](
29
+ const std::string& topic,
30
+ const std::string& payload,
31
+ const MqttProperties& mqttProps)
26
32
  {
27
- _receiveMessage(topic, payload, optCorrelationId, optResultCode);
33
+ _receiveMessage(topic, payload, mqttProps);
28
34
  });
29
35
 
30
36
  {%-for sig_name, sig in stinger.signals.items() %}
31
- _broker->Subscribe("{{sig.topic}}", 1);
32
- {%endfor%}
37
+ _{{sig_name | lowerCamelCase}}SignalSubscriptionId = _broker->Subscribe("{{sig.topic}}", 2);
38
+ {%-endfor%}
33
39
  {%-for method_name, method in stinger.methods.items() %}
34
40
  { // Restrict scope
35
41
  std::stringstream responseTopicStringStream;
@@ -37,21 +43,24 @@ constexpr const char {{stinger.cpp.client_class_name}}::INTERFACE_VERSION[];
37
43
  _broker->Subscribe(responseTopicStringStream.str(), 2);
38
44
  }
39
45
  {%-endfor%}
46
+
47
+ {%-for prop_name, prop in stinger.properties.items() %}
48
+ _{{prop_name | lowerCamelCase}}PropertySubscriptionId = _broker->Subscribe("{{prop.update_topic}}", 1);
49
+ {%-endfor%}
40
50
  }
41
51
 
42
52
  void {{stinger.cpp.client_class_name}}::_receiveMessage(
43
53
  const std::string& topic,
44
54
  const std::string& payload,
45
- const boost::optional<std::string> optCorrelationId,
46
- const boost::optional<MethodResultCode> optResultCode)
55
+ const MqttProperties& mqttProps)
47
56
  {
48
57
  {%-for sig_name, sig in stinger.signals.items() %}
49
- if (_broker->TopicMatchesSubscription(topic, "{{sig.topic}}"))
58
+ if ((mqttProps.subscriptionId && (*mqttProps.subscriptionId == _{{sig_name | lowerCamelCase}}SignalSubscriptionId)) || _broker->TopicMatchesSubscription(topic, "{{sig.topic}}"))
50
59
  {
51
60
  //Log("Handling {{sig_name}} signal");
52
61
  rapidjson::Document doc;
53
62
  try {
54
- if (_{{sig_name | camelCase}}Callback)
63
+ if (_{{sig_name | camelCase}}SignalCallbacks.size() > 0)
55
64
  {
56
65
  rapidjson::ParseResult ok = doc.Parse(payload.c_str());
57
66
  if (!ok)
@@ -82,9 +91,11 @@ void {{stinger.cpp.client_class_name}}::_receiveMessage(
82
91
  {%endif%}
83
92
  }
84
93
  }
85
- {%endfor%}
86
-
87
- _{{sig_name | camelCase}}Callback({%for arg in sig.arg_list%}temp{{arg.name}}{%if not loop.last%}, {%endif%}{%endfor%});
94
+ {%endfor%}{# for signal args #}
95
+ for (const auto& cb : _{{sig_name | lowerCamelCase}}SignalCallbacks)
96
+ {
97
+ cb({%for arg in sig.arg_list%}temp{{arg.name}}{%if not loop.last%}, {%endif%}{%endfor%});
98
+ }
88
99
  }
89
100
  }
90
101
  catch (const boost::bad_lexical_cast&)
@@ -94,21 +105,29 @@ void {{stinger.cpp.client_class_name}}::_receiveMessage(
94
105
  // TODO: Log this failure
95
106
  }
96
107
  }
97
- {%-endfor%}
108
+ {%-endfor%}{# for signals #}
109
+
98
110
  {%-for method_name, method in stinger.methods.items() %}
99
- {%if not loop.first%}else {%endif%}if (_broker->TopicMatchesSubscription(topic, "{{method.response_topic('+')}}") && optCorrelationId)
111
+ {%if not loop.first%}else {%endif%}if (_broker->TopicMatchesSubscription(topic, "{{method.response_topic('+')}}") && mqttProps.correlationId)
100
112
  {
101
113
  std::cout << "Matched topic for {{method_name}} response" << std::endl;
102
- _handle{{method_name|UpperCamelCase}}Response(topic, payload, *optCorrelationId);
114
+ _handle{{method_name|UpperCamelCase}}Response(topic, payload, *mqttProps.correlationId);
103
115
  }
104
- {%-endfor%}
116
+ {%-endfor%}{# for methods #}
117
+
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.update_topic}}")
120
+ {
121
+ _receive{{prop_name | UpperCamelCase}}PropertyUpdate(topic, payload, mqttProps.propertyVersion);
122
+ }
123
+ {%-endfor%}{# for properties #}
105
124
  }
106
125
 
107
126
 
108
127
  {%-for sig_name, sig in stinger.signals.items() %}
109
128
  void {{stinger.cpp.client_class_name}}::register{{sig_name | UpperCamelCase}}Callback(const std::function<void({%for arg in sig.arg_list%}{{arg.cpp_type}}{%if not loop.last%}, {%endif%}{%endfor%})>& cb)
110
129
  {
111
- _{{sig_name | camelCase}}Callback = cb;
130
+ _{{sig_name | lowerCamelCase}}SignalCallbacks.push_back(cb);
112
131
  }
113
132
  {%-endfor%}
114
133
 
@@ -122,31 +141,19 @@ boost::future<{{method.return_value_cpp_class}}> {{stinger.cpp.client_class_name
122
141
  rapidjson::Document doc;
123
142
  doc.SetObject();
124
143
 
125
- {%-macro addToDoc(arg)%}
126
- {%-if arg.arg_type.name.lower() == 'primitive'%}
127
- {%-if arg.optional %}if ({{arg.name}}) {%endif-%}
128
- {%-if arg.type.name.lower() == 'string'%}
129
- { // restrict scope
130
- rapidjson::Value tempStringValue;
131
- tempStringValue.SetString({{arg.name}}{%-if arg.optional %}->{%else%}.{%endif-%}c_str(), {{arg.name}}.size(), doc.GetAllocator());
132
- doc.AddMember("{{arg.name}}", tempStringValue, doc.GetAllocator());
133
- }
134
- {%-else%}
135
- doc.AddMember("{{arg.name}}", {%-if arg.optional %}*{%endif-%}{{arg.name}}, doc.GetAllocator());
136
- {%-endif%}
137
- {%elif arg.arg_type.name.lower() == 'enum'%}
138
- doc.AddMember("{{arg.name}}", static_cast<int>({{arg.name}}), doc.GetAllocator());
139
- {%-endif-%}
140
- {%endmacro%}
141
144
  {%for arg in method.arg_list%}
142
- {{addToDoc(arg)}}
145
+ {{ser.addToValue('doc', arg, 'doc.GetAllocator()') | indent(4)}}
143
146
  {%endfor%}
144
147
  rapidjson::StringBuffer buf;
145
148
  rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
146
149
  doc.Accept(writer);
147
150
  std::stringstream responseTopicStringStream;
148
151
  responseTopicStringStream << boost::format("{{method.response_topic('%1%')}}") % _broker->GetClientId();
149
- _broker->Publish("{{method.topic}}", buf.GetString(), 2, false, correlationIdStr, responseTopicStringStream.str(), MethodResultCode::SUCCESS);
152
+ MqttProperties mqttProps;
153
+ mqttProps.correlationId = correlationIdStr;
154
+ mqttProps.responseTopic = responseTopicStringStream.str();
155
+ mqttProps.resultCode = MethodResultCode::SUCCESS;
156
+ _broker->Publish("{{method.topic}}", buf.GetString(), 2, false, mqttProps);
150
157
 
151
158
  return _pending{{method_name|UpperCamelCase}}MethodCalls[correlationId].get_future();
152
159
  }
@@ -204,4 +211,70 @@ void {{stinger.cpp.client_class_name}}::_handle{{method_name|UpperCamelCase}}Res
204
211
 
205
212
  std::cout << "End of response handler for " << topic << std::endl;
206
213
  }
207
- {%endfor%}
214
+ {%endfor%}{# end for each method #}
215
+ {%for prop_name, prop in stinger.properties.items()%}
216
+ void {{stinger.cpp.client_class_name}}::_receive{{prop_name | UpperCamelCase}}PropertyUpdate(const std::string& topic, const std::string& payload, boost::optional<int> optPropertyVersion)
217
+ {
218
+ rapidjson::Document doc;
219
+ rapidjson::ParseResult ok = doc.Parse(payload.c_str());
220
+ if (!ok)
221
+ {
222
+ //Log("Could not JSON parse {{prop_name}} property update payload.");
223
+ throw std::runtime_error(rapidjson::GetParseError_En(ok.Code()));
224
+ }
225
+
226
+ if (!doc.IsObject()) {
227
+ throw std::runtime_error("Received {{prop_name}} payload is not an object");
228
+ }
229
+ {{prop.name | UpperCamelCase}}Property tempValue;
230
+ {{deser.deserialize('tempValue', prop.arg_list, 'doc') | indent(4)}}
231
+
232
+ { // Scope lock
233
+ std::lock_guard<std::mutex> lock(_{{prop_name | lowerCamelCase}}PropertyMutex);
234
+ _{{prop_name | lowerCamelCase}}Property = tempValue;
235
+ _last{{prop_name | UpperCamelCase}}PropertyVersion = optPropertyVersion ? *optPropertyVersion : -1;
236
+ }
237
+ // Notify all registered callbacks.
238
+ { // Scope lock
239
+ std::lock_guard<std::mutex> lock(_{{prop_name | lowerCamelCase}}PropertyCallbacksMutex);
240
+ for (const auto& cb : _{{prop_name | lowerCamelCase}}PropertyCallbacks)
241
+ {
242
+ // Don't need a mutex since we're using tempValue.
243
+ {%if prop.arg_list | length > 1 %}
244
+ cb({%for arg in prop.arg_list %}tempValue.{{arg.name}}{%if not loop.last%}, {%endif%}{%endfor%});
245
+ {%else %}
246
+ cb(tempValue);
247
+ {%endif %}
248
+ }
249
+ }
250
+ }
251
+
252
+ boost::optional<{{prop_value_type(prop)}}> {{stinger.cpp.client_class_name}}::get{{prop_name | UpperCamelCase}}Property() const
253
+ {
254
+ std::lock_guard<std::mutex> lock(_{{prop_name | lowerCamelCase}}PropertyMutex);
255
+ return _{{prop_name | lowerCamelCase}}Property;
256
+ }
257
+
258
+ void {{stinger.cpp.client_class_name}}::register{{prop_name | UpperCamelCase}}PropertyCallback(const std::function<void({{ar.methodParams(prop.arg_list)}})>& cb)
259
+ {
260
+ std::lock_guard<std::mutex> lock(_{{prop_name | lowerCamelCase}}PropertyCallbacksMutex);
261
+ _{{prop_name | lowerCamelCase}}PropertyCallbacks.push_back(cb);
262
+ }
263
+ {% if not prop.read_only %}
264
+ boost::future<bool> {{stinger.cpp.client_class_name}}::update{{prop_name | UpperCamelCase}}Property({{ar.methodParams(prop.arg_list)}}) const
265
+ {
266
+
267
+ rapidjson::Document doc;
268
+ doc.SetObject();
269
+ {%for item in prop.arg_list %}
270
+ {{ser.addToValue('doc', item, 'doc.GetAllocator()') | indent(4)}}
271
+ {%endfor %}
272
+ rapidjson::StringBuffer buf;
273
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
274
+ doc.Accept(writer);
275
+ MqttProperties mqttProps;
276
+ return _broker->Publish("{{prop.update_topic}}", buf.GetString(), 1, false, mqttProps);
277
+
278
+ }
279
+ {%endif%}
280
+ {% endfor %} {# for properties #}
@@ -0,0 +1,25 @@
1
+ {% import "partials/deserialize.jinja2" as deser %}
2
+ {% import "partials/serialize.jinja2" as ser %}
3
+ #include "property_structs.hpp"
4
+ #include <rapidjson/document.h>
5
+
6
+ {%for prop_name, prop in stinger.properties.items()%}
7
+ {%- if prop.arg_list| length > 1 %}
8
+ {{prop.name | UpperCamelCase}}Property {{prop.name | UpperCamelCase}}Property::FromRapidJsonObject(const rapidjson::Value& jsonObj)
9
+ {
10
+ {{prop.name | UpperCamelCase}}Property {{prop.name | lowerCamelCase }};
11
+ {{deser.deserialize(prop.name|lowerCamelCase, prop.arg_list, 'jsonObj') | indent(4)}}
12
+
13
+ return {{prop.name | lowerCamelCase}};
14
+ };
15
+
16
+ rapidjson::Value {{prop.name | UpperCamelCase}}Property::ToRapidJsonObject(rapidjson::Document::AllocatorType& allocator) const
17
+ {
18
+ rapidjson::Value obj(rapidjson::kObjectType);
19
+ {%for arg in prop.arg_list%}
20
+ {{ser.addToValue('obj', arg, 'allocator') | indent(4)}}
21
+ {%- endfor %}
22
+ return obj;
23
+ }
24
+ {%- endif %}
25
+ {% endfor %}
@@ -1,4 +1,6 @@
1
1
 
2
+ {% import "partials/serialize.jinja2" as ser %}
3
+
2
4
  #include <vector>
3
5
  #include <iostream>
4
6
  #include <boost/format.hpp>
@@ -19,9 +21,12 @@ constexpr const char {{stinger.cpp.server_class_name}}::NAME[];
19
21
  constexpr const char {{stinger.cpp.server_class_name}}::INTERFACE_VERSION[];
20
22
 
21
23
  {{stinger.cpp.server_class_name}}::{{stinger.cpp.server_class_name}}(std::shared_ptr<IBrokerConnection> broker) : _broker(broker) {
22
- _broker->AddMessageCallback([this](const std::string& topic, const std::string& payload, const boost::optional<std::string> optCorrelationId, const boost::optional<std::string> optResponseTopic, const boost::optional<MethodResultCode> unusedRc)
24
+ _broker->AddMessageCallback([this](
25
+ const std::string& topic,
26
+ const std::string& payload,
27
+ const MqttProperties& mqttProps)
23
28
  {
24
- _receiveMessage(topic, payload, optCorrelationId, optResponseTopic);
29
+ _receiveMessage(topic, payload, mqttProps);
25
30
  });
26
31
  {%for method in stinger.methods.values()%}
27
32
  _broker->Subscribe("{{method.topic}}", 2);
@@ -31,8 +36,7 @@ constexpr const char {{stinger.cpp.server_class_name}}::INTERFACE_VERSION[];
31
36
  void {{stinger.cpp.server_class_name}}::_receiveMessage(
32
37
  const std::string& topic,
33
38
  const std::string& payload,
34
- const boost::optional<std::string> optCorrelationId,
35
- const boost::optional<std::string> optResponseTopic)
39
+ const MqttProperties& mqttProps)
36
40
  {
37
41
  {%for method_name, method in stinger.methods.items()%}
38
42
  if (_broker->TopicMatchesSubscription(topic, "{{method.topic}}"))
@@ -53,7 +57,7 @@ void {{stinger.cpp.server_class_name}}::_receiveMessage(
53
57
  throw std::runtime_error("Received payload is not an object");
54
58
  }
55
59
 
56
- _call{{method_name | UpperCamelCase}}Handler(topic, doc, optCorrelationId, optResponseTopic);
60
+ _call{{method_name | UpperCamelCase}}Handler(topic, doc, mqttProps.correlationId, mqttProps.responseTopic);
57
61
  }
58
62
  }
59
63
  catch (const boost::bad_lexical_cast&)
@@ -71,29 +75,14 @@ boost::future<bool> {{stinger.cpp.server_class_name}}::emit{{sig_name | UpperCam
71
75
  {
72
76
  rapidjson::Document doc;
73
77
  doc.SetObject();
74
- {%macro addToDoc(arg)%}
75
- {%-if arg.optional%}if ({{arg.name}}){%endif%}
76
- {%-if arg.arg_type.name.lower() == 'primitive'%}
77
- {%-if arg.type.name.lower() == 'string'%}
78
- { // restrict scope
79
- rapidjson::Value tempStringValue;
80
- tempStringValue.SetString({{arg.name}}{%-if arg.optional%}->{%else%}.{%endif%}c_str(), {{arg.name}}.size(), doc.GetAllocator());
81
- doc.AddMember("{{arg.name}}", tempStringValue, doc.GetAllocator());
82
- }
83
- {%-else%}
84
- doc.AddMember("{{arg.name}}", {%-if arg.optional%}*{%endif%}{{arg.name}}, doc.GetAllocator());
85
- {%-endif%}
86
- {%-elif arg.arg_type.name.lower() == 'enum'%}
87
- doc.AddMember("{{arg.name}}", static_cast<int>({%-if arg.optional%}*{%endif%}{{arg.name}}), doc.GetAllocator());
88
- {%-endif-%}
89
- {%-endmacro%}
90
78
  {%-for arg in sig.arg_list%}
91
- {{addToDoc(arg)}}
92
- {%endfor%}
79
+ {{ser.addToValue('doc', arg, 'doc.GetAllocator()') | indent}}
80
+ {%-endfor%}
93
81
  rapidjson::StringBuffer buf;
94
82
  rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
95
83
  doc.Accept(writer);
96
- return _broker->Publish("{{sig.topic}}", buf.GetString(), 1, false, boost::none, boost::none, boost::none);
84
+ MqttProperties mqttProps;
85
+ return _broker->Publish("{{sig.topic}}", buf.GetString(), 1, false, mqttProps);
97
86
  }
98
87
  {%endfor%}
99
88
 
@@ -163,7 +152,10 @@ void {{stinger.cpp.server_class_name}}::_call{{method_name | UpperCamelCase}}Han
163
152
  rapidjson::StringBuffer buf;
164
153
  rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
165
154
  responseJson.Accept(writer);
166
- _broker->Publish(*optResponseTopic, buf.GetString(), 2, false, optCorrelationId, boost::none, MethodResultCode::SUCCESS);
155
+ MqttProperties mqttProps;
156
+ mqttProps.correlationId = optCorrelationId;
157
+ mqttProps.resultCode = MethodResultCode::SUCCESS;
158
+ _broker->Publish(*optResponseTopic, buf.GetString(), 2, false, mqttProps);
167
159
  }
168
160
  }
169
161
  }
@@ -0,0 +1,13 @@
1
+ {% import "partials/deserialize.jinja2" as deser %}
2
+ #include "structs.hpp"
3
+
4
+
5
+ {%for istruct_name, istruct in stinger.structs.items() %}
6
+ {{istruct_name | UpperCamelCase }} {{istruct_name | UpperCamelCase }}::FromRapidJsonObject(const rapidjson::Value& jsonObj)
7
+ {
8
+ {{istruct_name | UpperCamelCase }} {{istruct_name | lowerCamelCase }};
9
+ {{deser.deserialize(istruct_name|lowerCamelCase, istruct.members, 'jsonObj') | indent(4)}}
10
+
11
+ return {{istruct_name | lowerCamelCase}};
12
+ };
13
+ {%endfor%}
@@ -1,14 +1,14 @@
1
1
  const clientId = "{{stinger.name}}-web-" + new Date().getTime();
2
2
 
3
- const signalSubIdStart = 1;
4
- const propertySubIdStart = {{10 + stinger.signals|length}};
3
+ const responseTopic = "client/" + clientId + "/responses";
4
+ var responseSubscriptionId = null;
5
5
 
6
6
  function makeRequestProperties() {
7
7
  const correlationData = Math.random().toString(16).substr(2, 8);
8
8
  return {
9
9
  "contentType": "application/json",
10
10
  "correlationData": correlationData,
11
- "responseTopic": responseTopic + correlationData
11
+ "responseTopic": responseTopic
12
12
  }
13
13
  }
14
14
 
@@ -22,17 +22,58 @@ app.controller("myCtrl", function ($scope, $filter, $location) {
22
22
 
23
23
  $scope.timePattern = new RegExp("^[0-2][0-9]:[0-5][0-9]$");
24
24
  $scope.online = false;
25
+
26
+ $scope.enums = {
27
+ {%-for enum_name, enum in stinger.enums.items() %}
28
+ // {{enum}}
29
+ "{{enum_name | snake_case}}": [
30
+ {%-for e in enum.values %}
31
+ {"name": "{{e}}", "id": {{loop.index}} }{%if not loop.last%},{%endif%}
32
+ {%endfor-%}
33
+ ]{%if not loop.last%},{%endif%}
34
+ {%endfor-%} };
35
+
25
36
  $scope.signals = { {%-for sig_name, signal in stinger.signals.items() %}
26
- "{{sig_name | lowerCamelCase}}": {
37
+ "{{sig_name | snake_case}}": {
27
38
  "subscription_id": null,
28
39
  "name": "{{sig_name}}",
29
- "received": [],
40
+ "received": null,
41
+ "received_time": null,
30
42
  "mqtt_topic": "{{signal.topic}}"
31
43
  }{%if not loop.last%},{%endif%}
32
44
  {%endfor-%} };
33
45
 
34
- $scope.properties = {
46
+ $scope.properties = { {%-for prop_name, prop in stinger.properties.items() %}
47
+ "{{prop_name | snake_case}}": {
48
+ "subscription_id": null,
49
+ "name": "{{prop_name}}",
50
+ "received": { {%for arg in prop.arg_list %}
51
+ "{{arg.name|snake_case}}": {%if arg.type == "argtype.primitive"%}{%else%}{ {%for member in arg.members %}
52
+ "{{member.name|snake_case}}": "{{member.value}}"{%if not loop.last%},{%endif%}
53
+ {%endfor%} }{%endif%}{%if not loop.last%},{%endif%}
54
+ {%endfor%} },
55
+ "mqtt_topic": "{{prop.value_topic}}"{%if not prop.read_only %},
56
+ "update_topic": "{{prop.update_topic}}"{%endif%}
57
+ }{%if not loop.last%},{%endif%}
58
+ {%endfor-%} };
35
59
 
60
+ $scope.methods = {
61
+ {%-for method_name, method in stinger.methods.items() %}
62
+ "{{method_name | snake_case}}": {
63
+ "name": "{{method_name}}",
64
+ "mqtt_topic": "{{method.topic}}",
65
+ "response_topic": "{{method.response_topic('"+clientId+"')}}",
66
+ "pending_correlation_id": null,
67
+ "args": { {%-for arg in method.arg_list %}
68
+ "{{arg.name|snake_case}}": {
69
+ "type": "{{arg.type}}",
70
+ "value": null
71
+ }{%if not loop.last%},{%endif%}
72
+ {%endfor-%} },
73
+ "received": null,
74
+ "received_time": null
75
+ }{%if not loop.last%},{%endif%}
76
+ {%-endfor%}
36
77
  };
37
78
 
38
79
  $scope.console = {
@@ -63,26 +104,17 @@ app.controller("myCtrl", function ($scope, $filter, $location) {
63
104
  console.log(name + " Sending to " + topic);
64
105
  console.log(payload);
65
106
  let props = makeRequestProperties();
66
- props
67
107
  $scope.console.requests.unshift({"name":name, "correlationData":props.correlationData, "topic": topic, "payload": payload, "response": null, "requestTime": Date.now()});
68
108
  client.publish(topic, payload, { "qos": qos, retain: false, properties: props});
69
109
  return props.correlationData;
70
110
  }
71
111
 
72
112
  client.on('message', function(topic, message, packet) {
73
- console.log("Message Arrived: " + topic);
74
-
113
+
75
114
  const subid = packet.properties.subscriptionIdentifier;
76
115
 
77
- if (subid >= signalSubIdStart && subid < propertySubIdStart) {
78
- const signal_index = subid - signalSubIdStart;
79
- console.log("Signal index: " + signal_index);
80
- $scope.data.signals[signal_index] = JSON.parse(message.toString());
81
- } else if (subid >= propertySubIdStart && subid < propertySubIdStart + {{stinger.properties|length}}) {
82
- const prop_index = subid - propertySubIdStart;
83
- console.log("Property index: " + prop_index);
84
- $scope.data.properties[prop_index] = JSON.parse(message.toString());
85
- }
116
+ console.log("Message Arrived: " + topic + " (" + subid + ")");
117
+ console.log($scope.properties);
86
118
 
87
119
  var obj;
88
120
  if (message.toString().length == 0) {
@@ -92,34 +124,103 @@ app.controller("myCtrl", function ($scope, $filter, $location) {
92
124
  }
93
125
  console.log(obj);
94
126
 
127
+ for (const key in $scope.signals) {
128
+ if (!$scope.signals.hasOwnProperty(key)) continue;
129
+ const sig = $scope.signals[key];
130
+ if (sig.subscription_id == subid) {
131
+ sig.received = obj;
132
+ sig.received_time = new Date();
133
+ }
134
+ }
135
+ for (const key in $scope.properties) {
136
+ if (!$scope.properties.hasOwnProperty(key)) continue;
137
+ const prop = $scope.properties[key];
138
+ if (prop.subscription_id == subid) {
139
+ prop.received = obj;
140
+ console.log("Set property received object to ", prop.received);
141
+ }
142
+ }
143
+ for (const key in $scope.methods) {
144
+ if (!$scope.methods.hasOwnProperty(key)) continue;
145
+ const method = $scope.methods[key];
146
+ if (responseSubscriptionId == subid) {
147
+ if (packet.properties.correlationData && method.pending_correlation_id == packet.properties.correlationData) {
148
+ method.received = obj;
149
+ method.received_time = new Date();
150
+ for (let i=0; i<$scope.console.requests.length; i++) {
151
+ const req = $scope.console.requests[i];
152
+ if (req.correlationData == packet.properties.correlationData) {
153
+ req.response = obj;
154
+ req.responseTime = Date.now();
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+
95
161
  $scope.$apply();
96
162
  });
97
163
 
98
164
  client.on('connect', function() {
165
+ $scope.online = true;
166
+
167
+ var subscription_count = 10;
99
168
  console.log("Connected with ", client);
100
- {%for signal_name, signal in stinger.signals.items() %}
101
- const {{sig_name}}_sub_opts = {
169
+
170
+ var responseSubscriptionId = subscription_count++;
171
+ const responseSubOpts = {
102
172
  "qos": 1,
103
173
  "properties": {
104
- "subscriptionIdentifier": (signalSubIdStart + {{loop.index}})
174
+ "subscriptionIdentifier": responseSubscriptionId
105
175
  }
106
176
  };
107
- client.subscribe("{{signal.topic}}", {{sig_name}}_sub_opts);
108
- console.log("Subscribing to {{signal.topic}} with id {{loop.index}}");
109
- {%endfor%}
110
- {%for prop_name, prop in stinger.properties.items() %}
111
- const {{prop_name}}_sub_opts = {
177
+ client.subscribe(responseTopic, responseSubOpts);
178
+ console.log("Subscribing to response topic " + responseTopic + " with id " + responseSubscriptionId);
179
+
180
+ {%for signal_name, signal in stinger.signals.items() %}
181
+ const {{signal_name|snake_case}}_sub_opts = {
112
182
  "qos": 1,
113
183
  "properties": {
114
- "subscriptionIdentifier": (propertySubIdStart + {{loop.index}})
184
+ "subscriptionIdentifier": subscription_count
115
185
  }
116
186
  };
117
- client.subscribe("{{prop.value_topic}}", {{prop_name}}_sub_opts);
118
- console.log("Subscribing to {{prop.value_topic}} with id {{loop.index + stinger.signals|length}}");
187
+ $scope.signals["{{signal_name | lowerCamelCase}}"].subscription_id = subscription_count;
188
+ client.subscribe("{{signal.topic}}", {{signal_name|snake_case}}_sub_opts);
189
+ console.log("Subscribing to signal {{signal.topic}} with id ", subscription_count);
190
+ subscription_count++;
119
191
  {%endfor%}
192
+
193
+ for (const key in $scope.properties) {
194
+ if (!$scope.properties.hasOwnProperty(key)) continue;
195
+ var sub_id = subscription_count++;
196
+ const prop_sub_opts = {
197
+ "qos": 1,
198
+ "properties": {
199
+ "subscriptionIdentifier": sub_id
200
+ }
201
+ };
202
+ $scope.properties[key].subscription_id = sub_id;
203
+ client.subscribe($scope.properties[key].mqtt_topic, prop_sub_opts);
204
+ console.log("Subscribing to property " + $scope.properties[key].mqtt_topic + " with id " + $scope.properties[key].subscription_id);
205
+ }
206
+
120
207
  subscription_state = 1;
121
208
  $scope.$apply();
122
209
  });
123
210
 
211
+ $scope.updateProperty = function(prop) {
212
+ const payload = JSON.stringify(prop.received);
213
+ publish("Property Update", prop.update_topic, payload, 1);
214
+ };
124
215
 
216
+ $scope.callMethod = function(method) {
217
+ const payload = {};
218
+ for (const key in method.args) {
219
+ if (!method.args.hasOwnProperty(key)) continue;
220
+ payload[key] = method.args[key].value;
221
+ }
222
+ const payload_str = JSON.stringify(payload);
223
+ console.log("Method Call", method.mqtt_topic, payload_str, 1);
224
+ method.pending_correlation_id = publish("Method Call", method.mqtt_topic, payload_str, 1);
225
+ };
125
226
  });