You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge pull request #8 from openDAQ/json-subscriber-reworking
Json subscriber reworking
- Rework of JSON subscription flow: JSON receiver FB no longer parses all signals itself — it now creates nested JSON decoder function blocks (jsonDecoderMqttFb) that parse individual values/timestamps and produce signals.
- New JSON decoder FB: added mqtt_json_decoder_fb_impl.{h,cpp} to extract a single value + optional timestamp from incoming JSON and emit data/domain samples.
- JSON config handling changed: SignalList (big JSON string) → JsonConfig (string) and JsonConfigFile (path). JSON FB reads config (or file), extracts topic and per-signal descriptors and creates nested decoders. New "Topic" property.
- Stronger topic validation and subscription QoS: added PROPERTY_NAME_SUB_QOS / DEFAULT_SUB_QOS; subscription/unsubscribe now use the configured QoS.
- Status system refactor: introduced a generic StatusHelper to manage enumerated statuses (component / subscription / parsing / publishing / setting), replacing many manual EnumerationWithIntValue usages.
Publisher FB improvements: cleaner status reporting (SignalStatus / PublishingStatus / SettingStatus), validation of properties (QoS, topic when sharedTs or multi), rename of publishing modes to descriptive enum names, and more robust publishing status tracking.
- Raw FB changes: Topic property replaced SignalList.
- MqttDataWrapper changes: JSON parsing & descriptor extraction reworked (now returns per-signal MqttMsgDescriptor with unit info), value/timestamp extraction refactored; API signatures changed.
- Tests and examples: many unit tests added / updated (including new test for json decoder), new example JSON files for tests, updates to examples (custom-mqtt-sub, raw-mqtt-sub, ref-dev-mqtt-pub) to use the new FB/type/property names and behavior.
- Renames & cleanups: several handler/source/header files renamed to clearer names (single_handler → atomic_signal_atomic_sample_handler, multisingle → atomic_signal_sample_arr_handler, multiple_shared → group_signal_shared_ts_handler, multiple → signal_arr_atomic_sample_handler), constants and FB type IDs removed leading '@' (e.g. @rootMqttFb → rootMqttFb), and general code cleanup (status helper, removal of old helper functions).
Copy file name to clipboardExpand all lines: README.md
+30-15Lines changed: 30 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,17 +2,17 @@
2
2
3
3
## Description
4
4
5
-
MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The module is designed for software communication via the *MQTT 3.1.1* protocol using an external broker. It allows publishing and subscribing to openDAQ signal data over MQTT. The module consists of four key openDAQ components: the *MQTT device*and its nested function blocks — the *publisher* (**@publisherMqttFb**), the *raw subscriber* (**@rawMqttFb**), and the *JSON subscriber* (**@jsonMqttFb**).
5
+
MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The module is designed for software communication via the *MQTT 3.1.1* protocol using an external broker. It allows publishing and subscribing to openDAQ signal data over MQTT. The module consists of five key openDAQ components: the *MQTT root function block* (**rootMqttFb**) and its nested function blocks — the *publisher* (**publisherMqttFb**) with its nested block *JSON decoder* (**jsonDecoderMqttFb**) , the *raw subscriber* (**rawMqttFb**), and the *JSON subscriber* (**jsonMqttFb**).
6
6
7
7
### Functional
8
8
- Connecting to an MQTT broker;
9
9
- Publishing openDAQ signals as MQTT messages (*publisher FB*);
10
-
- Subscribing to MQTT topics and converting incoming messages into openDAQ signals (*raw FB and JSON FB*);
10
+
- Subscribing to MQTT topics and converting incoming messages into openDAQ signals (*raw FB and JSON FB + JSON decoder FB*);
11
11
- Support for multiple message types and formats for both publishing and subscribing;
12
12
- A set of examples and *gtests* for verifying functionality.
-**Purpose**: Represents the MQTT broker as an openDAQ function block - the connection point through which function blocks are created.
18
18
-**Main properties:**
@@ -21,7 +21,7 @@ MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The modul
21
21
-*MqttUsername* (string) — Username for MQTT broker authentication. By default, it is empty.
22
22
-*MqttPassword* (string) — Password for MQTT broker authentication. By default, it is empty.
23
23
-*ConnectTimeout* (integer) — Timeout in milliseconds for the initial connection to the MQTT broker. If the connection fails, an exception is thrown. By default, it is set to *3000 ms*.
24
-
2)**Publisher MQTT Function Block (@publisherMqttFb)**:
24
+
2)**Publisher MQTT Function Block (publisherMqttFb)**:
-**Purpose**: Publishes openDAQ signal data to MQTT topics. There are **four** general data publishing schemes:
27
27
1) One MQTT message per signal / one message per sample / one topic per signal / one timestamp for each sample. Example: *{"AI0": 1.1, "timestamp": 1763716736100000}*
@@ -37,6 +37,7 @@ MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The modul
37
37
-**Main properties**:
38
38
-*TopicMode* (list) — Selects whether to publish all signals to separate MQTT topics (one per signal, *single-topic mode*) or to a single topic (*multiple-topic mode*), one for all signals. Choose *0* for *single-topic* mode and *1* for *multiple-topic* mode. By default, it is set to *single-topic* mode.
39
39
-*MqttQoS* (integer) — MQTT Quality of Service level. It can be *0* (at most once), *1* (at least once), or *2* (exactly once). By default, it is set to *1*.
40
+
-*Topic* (string) — Topic name for publishing in multiple-topic mode. If left empty, the Publisher's *Global ID* is used as the topic name.
40
41
-*SharedTimestamp* (bool) — Enables the use of a shared timestamp for all signals when publishing in *multiple-topic* mode. By default, it is set to *false*.
41
42
-*GroupValues* (bool) — Enables the use of a sample pack for a signal when publishing in *single-topic* mode. By default, it is set to *false*.
42
43
-*UseSignalNames* (bool) — Uses signal names as JSON field names instead of Global IDs. By default, it is set to *false*.
@@ -50,18 +51,22 @@ MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The modul
-**Purpose**: Subscribes to raw MQTT messages and converts them into openDAQ signals (binary data) without any parsing — suitable for binary/unstructured messages or simple numeric values.
57
58
-**Main properties**:
58
-
-*SignalList* (list of strings) — List of MQTT topics to subscribe to for receiving raw binary data.
59
+
-*Topic* (string) — MQTT topic to subscribe to for receiving raw binary data.
60
+
-*MqttQoS* (integer) — MQTT Quality of Service level. It can be *0* (at most once), *1* (at least once), or *2* (exactly once). By default, it is set to *1*.
-**Purpose**: Subscribes to MQTT topics, extracts values and timestamps from MQTT JSON messages, and converts them into openDAQ signal data samples.
64
+
-**Purpose**: Subscribes to MQTT topics, extracts values and timestamps from MQTT JSON messages via nested *JSON decoder MQTT Function Blocks*.
63
65
-**Main properties**:
64
-
-*SignalList* (string) — **JSON configuration string** that defines the list of MQTT topics and the corresponding signals to subscribe to. A typical string structure:
66
+
-*Topic* (string) — MQTT topic to subscribe to for receiving JSON data.
67
+
-*MqttQoS* (integer) — MQTT Quality of Service level. It can be *0* (at most once), *1* (at least once), or *2* (exactly once). By default, it is set to *1*.
68
+
-*JsonConfigFile* (string) — path to file with **JSON configuration string**. See the *JsonConfig* property for more details. This property could be set only at creation. It is not visible.
69
+
-*JsonConfig* (string) — **JSON configuration string** that defines the MQTT topic and the corresponding signals to subscribe to. This property could be set only at creation. It is not visible. A typical string structure:
65
70
```json
66
71
{
67
72
"<topic>":[
@@ -71,8 +76,8 @@ MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The modul
@@ -112,11 +117,21 @@ MQTT module for the [OpenDAQ SDK](https://github.com/openDAQ/openDAQ). The modul
112
117
]
113
118
}
114
119
```
115
-
In this example, the *JSON MQTT Function Block* creates 3 signals, subscribes to the *"/mirip/UNet3AC2/sensor/data"* topic, and extracts 3 signal samples from each message (one sample per signal). The signals are named *“temp”*, *“humidity”*, and *“tds”*. The *“temp”* signal is created with a domain signal because the *“Timestamp”* field is present. Each domain-signal sample is extracted from the *“ts”* field of the JSON MQTT message. The value of the *“ts”* field (the timestamp field) may be in **ISO8601** format or **Unix epoch time** in seconds, milliseconds, or microseconds. The value of the *“temp”* signal sample is extracted from the *“temp”* field of the JSON message. The unit of the values is “°C”.
120
+
In this example, the *JSON MQTT Function Block* creates 3 nested *jsonDecoderMqttFb*, subscribes to the *"/mirip/UNet3AC2/sensor/data"* topic, and extracts 3 signal samples from each message (one sample per *jsonDecoderMqttFb*). The signals are named *“temp”*, *“humidity”*, and *“tds”*. The *“temp”* signal is created with a domain signal because the *“Timestamp”* field is present. Each domain-signal sample is extracted from the *“ts”* field of the JSON MQTT message. The value of the *“ts”* field (the timestamp field) may be in **ISO8601** format or **Unix epoch time** in seconds, milliseconds, or microseconds. The value of the *“temp”* signal sample is extracted from the *“temp”* field of the JSON message. The unit of the values is “°C”.
116
121
Example of JSON MQTT message for this configuration:
- **Purpose**: To parse JSON string data to extract a value and a timestamp, and to send data and domain samples based on this data.
130
+
- **Main properties**:
131
+
- *ValueName* (string) — indicates which JSON field contains the sample value.
132
+
- *TimestampName* (string) — indicates which JSON field contains the timestamp.
133
+
- *Unit* (string) — describes the unit symbol of the decoded signal value.
134
+
- *SignalName* (string) — specifies the name to assign to the signal created by a *jsonDecoderMqttFb*.
120
135
---
121
136
122
137
## Building MQTTStreamingModule
@@ -164,13 +179,13 @@ cmake --build .
164
179
## Examples
165
180
166
181
There are 3 example C++ application:
167
-
-**custom-mqtt-sub** - demonstrates how to work with the *JSON MQTT FB*. The application creates an *MQTT root FB* and a *JSON MQTT FB* to receive JSON MQTT messages, parse them, and create openDAQ signals to send the parsed data. The application also creates *packet readers* for all FB signals and prints the samples to standard output. The *SignalList* property of the JSON MQTT FB is set to the value read from a file whose path is provided as a command-line argument when the application starts (see the **Key components** section). Usage:
182
+
-**custom-mqtt-sub** - demonstrates how to work with the *JSON receiver MQTT FB* and *JSON decoder MQTT FB*. The application creates an *MQTT root FB* and a *JSON MQTT FB* to receive JSON MQTT messages, parse them, and create openDAQ signals to send the parsed data. The application also creates *packet readers* for all FB signals and prints the samples to standard output. The *JsonConfigFile* property of the JSON MQTT FB is set to the value of path whose is provided as a command-line argument when the application starts (see the **Key components** section). Usage:
-**raw-mqtt-sub** - demonstrates how to work with the *raw MQTT FB*. The application creates an *MQTT root FB* and a *raw MQTT FB* to receive MQTT messages and create openDAQ signals to send the data as binary packets. The application also creates packet readers for all FB signals and prints the binary packets as strings to standard output. The *SignalList* property of the raw MQTT FB is filled from the application arguments. Usage:
186
+
-**raw-mqtt-sub** - demonstrates how to work with the *raw MQTT FB*. The application creates an *MQTT root FB* and a *raw MQTT FB* to receive MQTT messages and create openDAQ signals to send the data as binary packets. The application also creates packet readers for all FB signals and prints the binary packets as strings to standard output. The *Topic* property of the raw MQTT FB is filled from the application arguments. Usage:
-**ref-dev-mqtt-pub** - demonstrates how to work with the *publisher MQTT FB*. The application creates an *openDAQ ref-device* with four channels, an *MQTT root FB*, and a *publisher MQTT FB* to publish JSON MQTT messages with the channels’ data. The properties of the *publisher MQTT FB* are set according to the selected mode, which can be specified via the *--mode* option. Posible values are:
176
191
- 0 - One MQTT message per signal / one message per sample / one topic per signal / one timestamp for each sample;
0 commit comments