Stand with Ukraine flag
Pricing Try it now
Cloud
North America
How to connect RN172plus series to ThingsBoard?
Getting Started Documentation Devices Library Guides API FAQ
On this page

How to connect RN172plus series to ThingsBoard?

Introduction

RN172plus series The RN172WCD by RADIONODE is a versatile Wi-Fi sensor data transmitter designed for real-time environmental monitoring in industrial, commercial, and laboratory settings.
It supports a wide range of UA series sensors, including gas detectors (CO₂, O₂, NH₃, etc.), thermal sensors (PT100, thermocouples), and analog transmitters (4–20 mA, 0–1 V), enabling flexible deployment across various applications.
With Wi-Fi (IEEE 802.11 b/g), MODBUS TCP, and HTTP/HTTPS connectivity, the device seamlessly transmits data to cloud platforms like Radionode365, local servers, or PLCs for centralized monitoring. Additional features include a built-in buzzer, dual-color LED indicators, and a 4-digit display for real-time readings and alerts.
The RN172WCD also supports remote configuration via Telnet and offers robust alarm functionalities, including SMS and voice call notifications, making it an ideal solution for safety-critical environments such as gas monitoring, HVAC systems, and industrial automation.

Prerequisites

To continue with this guide we will need the following:

Create device on ThingsBoard

For simplicity, we will create the device manually using the UI.

  • Log in to your ThingsBoard instance and navigate to Entities. Then open the Devices page.
  • Click the + icon in the top right corner of the table and select Add new device.
  • Enter a device name, for example, My Device. No other changes are required at this stage.
  • Click Add to create the device.

Your device has been successfully added.

image

Install required Payload decoders

After adding the device we need to create an Integration for creating the device connection with the thingsboard platform.

  • Click the integrations tab and start to add an integration by pressing the “+” sign.

image

  • Click the integrations tab and start to add an integration by selecting an integration type.

image

  • Here we are selecting the HTTP for our RN172 device.

image

  • Then add a name for the integration.

image

The next step is to create a data converter for our device.

  • Give a name to the data converter
  • Click the decoding configuration as js type and add the code given below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/**
 * Helper function to decode raw payload bytes to a string using a simple loop.
 * This method is more robust and compatible with older JS environments.
 */
function decodeToString(payload) {
    var text = "";
    var i = 0;
    while (i < payload.length) {
        text += String.fromCharCode(payload[i]);
        i++;
    }
    return text;
}

/**
 * Helper function to decode raw payload bytes to a JSON object.
 * It safely parses the string and returns a JSON object.
 */
function decodeToJson(payload) {
    try {
        var str = decodeToString(payload);
        return JSON.parse(str);
    } catch (e) {
        return null;
    }
}

/**
 * A custom parser to handle URL-encoded payloads.
 */
function parseUrlEncoded(payload) {
    var data = {};
    var bodyStr = decodeToString(payload).trim();
    if (bodyStr.indexOf('=') !== -1) {
        var pairs = bodyStr.split("&");
        var i = 0;
        while (i < pairs.length) {
            var parts = pairs[i].split("=");
            if (parts.length === 2) {
                var key = decodeURIComponent(parts[0].trim());
                var value = decodeURIComponent((parts[1] || "").trim());
                data[key] = value;
            }
            i++;
        }
    }
    return data;
}

// --- Main ThingsBoard Decode Function ---
function decodePayload(payload, metadata) {
    var deviceName = "Unknown_Device";
    var attributes = {};
    var telemetry = {};
    var telemetryTimestamp = null;
    var data = null;
    var detectedModel = null;

    // --- Model Lookup Table ---
    const ua_models_js = {
        "UA58-KFG": ["CO", "O2", "H2S", "CO2"],
        "UA58-CO2": ["CO2", "TEMP", "RH"],
        "UA58-DFG": ["CO", "CH2O", "C6H6"],
        "UA58-LEL": ["LEL", "TEMP", "RH", "CLAS"],
        "UA58-APC": ["CO2", "O3", "TEMP", "RH"],
        "UA50": ["TVOC", "ECO2"],
        "UA52-CO2": ["CO2", "TEMP"],
        "UA52-O2": ["O2", "TEMP"],
        "UA53-CO": ["CO", "TEMP", "RH"],
        "UA53-H2S": ["H2S", "TEMP", "RH"],
        "UA53-O3": ["O3", "TEMP", "RH"],
        "UA53-SO2": ["SO2", "TEMP", "RH"],
        "UA53-NO2": ["NO2", "TEMP", "RH"],
        "UA54-NH3": ["NH3", "TEMP", "RH"],
        "UA54-H2S": ["H2S", "TEMP", "RH"],
        "UA54-C2H4": ["C2H4", "TEMP", "RH"],
        "UA54-EO": ["EO", "TEMP", "RH"],
        "UA54-H2": ["H2", "TEMP", "RH"],
        "UA54-HCL": ["HCL", "TEMP", "RH"],
        "UA54-NO": ["NO", "TEMP", "RH"],
        "UA54-CL2": ["CL2", "TEMP", "RH"],
        "UA54-O2": ["O2", "TEMP", "RH"],
        "UA54-VOC": ["VOC", "TEMP", "RH"],
        "UA10": ["TEMP", "RH"],
        "UA11": ["TEMP", "TEMP"],
        "UA12": ["TEMP", "TEMP"],
        "UA13": ["TEMP"],
        "UA20A": ["mA", "mA"],
        "UA20B": ["mA"],
        "UA20C": ["mV", "mV"],
        "UA20D": ["Puls"],
        "UA20E": ["CH1", "CH2", "CH3", "CH4", "CH5", "CH6"],
        "UA59-CO2": ["CO2", "TEMP"],
        "UA60-PMVT": ["PM25", "PM10", "PM01", "TVOC", "TEMP", "RH"],
        "UA-DEVICE": ["TEMP", "RH"],
        "RN400-PG": [],
        "RN172WC": []
    };

    // --- Step 1: Payload Parsing ---
    var inputString = decodeToString(payload).trim();
    var atcqMatch = inputString.match(/ATCQ\s+([^,]+),([^,]+),([^,]+),([^,]+)/);
    
    if (atcqMatch) {
        // ATCQ payload format
        data = {};
        data.co2 = parseFloat(atcqMatch[1]);
        data.o3 = parseFloat(atcqMatch[2]);
        data.temperature = parseFloat(atcqMatch[3]);
        data.humidity = parseFloat(atcqMatch[4]);
        detectedModel = 'UA58-APC';
    } else {
        // Other payload formats (JSON, URL-encoded)
        data = decodeToJson(payload);
        if (!data) {
            data = parseUrlEncoded(payload);
        }
    }

    if (!data || Object.keys(data).length === 0) {
        return null;
    }

    // --- Step 2: Model Identification and Override ---
    var originalSModel = data.model || data.SMODEL;
    detectedModel = detectedModel || originalSModel;

    // Override the model if the payload structure matches UA58-APC.
    if (detectedModel === 'UA-DEVICE' && data.C000) {
        var channelData = data.C000.split('|').filter(x => x.trim() !== '');
        if (channelData.length === 5) {
            detectedModel = 'UA58-APC';
        }
    }

    var modelVars = ua_models_js[detectedModel];

    // --- Step 3: Process Telemetry and Attributes ---
    if (data.mac) {
        deviceName = data.mac;
        attributes.mac = data.mac;
    }
    if (data.ver) attributes.firmware = data.ver;
    if (originalSModel) attributes.SMODEL = originalSModel;
    if (data.model) attributes.model = data.model;
    if (detectedModel) attributes.detected_model = detectedModel;
    if (data.ip) attributes.ip = data.ip;
    if (data.splrate) attributes.samplingRate = parseFloat(data.splrate);
    if (data.rsti) attributes.rsti = parseFloat(data.rsti);
    if (data.interval) attributes.transmitInterval = parseFloat(data.interval);
    if (data.tags) attributes.tags = data.tags;

    // Process dynamic channels based on the detected model
    if (detectedModel && modelVars) {
        var dynamicKey;
        for (dynamicKey in data) {
            if (dynamicKey.match(/^(C|P|CH)\d+/)) {
                var channelData = data[dynamicKey].split('|').filter(x => x.trim() !== '');
                if (channelData.length > 1) {
                    telemetryTimestamp = parseInt(channelData[0]) * 1000;
                    var i = 0;
                    while (i < modelVars.length) {
                        var varName = modelVars[i];
                        if (varName !== '----') {
                            var value = parseFloat(channelData[i + 1]);
                            if (!isNaN(value)) {
                                telemetry[varName.toLowerCase()] = value;
                            }
                        }
                        i++;
                    }
                }
            }
        }
    }

    // Process static keys
    if (data.co2 !== undefined) telemetry.co2 = parseFloat(data.co2);
    if (data.o3 !== undefined) telemetry.o3 = parseFloat(data.o3);
    if (data.temperature !== undefined) telemetry.temperature = parseFloat(data.temperature);
    if (data.humidity !== undefined) telemetry.humidity = parseFloat(data.humidity);
    if (data.sig !== undefined) telemetry.signal = parseFloat(data.sig);
    if (data.bat !== undefined) telemetry.battery = parseFloat(data.bat);
    if (data.analog_1 !== undefined) telemetry.analog_1 = parseFloat(data.analog_1);
    if (data.analog_2 !== undefined) telemetry.analog_2 = parseFloat(data.analog_2);

    // Process RN172WC 'tags' payload separately
    if (detectedModel === "RN172WC" && data.tags) {
        var tagValues = data.tags.split('|').filter(s => s.trim() !== '');
        if (tagValues.length >= 2) {
            telemetry.temperature = parseFloat(tagValues[0].trim());
            telemetry.humidity = parseFloat(tagValues[1].trim());
        }
    }

    // If no telemetry values are found, add a heartbeat to ensure a valid payload
    if (Object.keys(telemetry).length === 0) {
        telemetry.heartbeat = Date.now();
    }
    
    // --- Step 4: Construct the final output object in the correct format ---
    var result = {
        deviceName: deviceName,
        telemetry: {}
    };

    var finalTelemetryTs = telemetryTimestamp || Date.now();
    for (var key in telemetry) {
        result.telemetry[key] = telemetry[key];
    }

    for (var key in attributes) {
        result.telemetry[key] = attributes[key];
    }
    
    // Return the formatted result for ThingsBoard.
    return result;
}

return decodePayload(payload, metadata);

image

  • Then completed the integration setup.

image

image

Connect device to ThingsBoard

  • Download the RadioNode terminal program
  • Run the RadioNode terminal program
  • Enter the password radionode114 and enter the console menu.

image

  • In the network setup we can add the Wi-Fi SSID and Password.

image)

  • Go to the “2. System Setup” menu and select “B. Set Destination of HTTP”.
  • Select “2:CUSTOMER_V2” from the three destinations.

This means the data will be sent to the custom server V2.

image

  • From the Integration tab of ThingsBoard, copy HTTP endpoint URL to set in the Radionode terminal program.

image

image

Go to the “4. HTTP Destination Setup” menu and select “A. Set Host URL:thingsboard.cloud” Select “D.Set HTTP DATAIN : endpoint from the integration”, “E.Set HTTP TIMESTAMP:endpoint from the integration”, “F.Set HTTP BACKUPIN :endpoint from the integration”.

Check data on ThingsBoard

Once the device is connected, On the devices page you can check the latest telemetry.

image

Setting up the Dashboard

Now configure the dashboard by adding the necessary widgets.

  • Go to the Dashboards page and press the + button to create a new Dashboard.

image

  • Enter a name for the Dashboard and then click the Add button.

image

After creation, the dashboard will open automatically, and you can start adding widgets right away. Click Add widget.

image

ThingsBoard provides many widget options to choose from. For example, select a Time series chart from the Charts widget bundle to visualize data from your device.

image

  • In the widget settings, you can define the display time window.
  • In the Datasource field, specify your device whose data you want to display. If you need to add another data series, click Add series.
  • Once configured, click Add. Don't forget to save the dashboard.

image

A sample dashboard featuring the Indoor temperature chart card, Indoor humidity chart card, and Temperature and Humidity history line chart.

You can download this dashboard in JSON format and import it into your own ThingsBoard instance.

image