Skip to main content

IIoT Example Collection

The examples below are patterns that are frequently built in the field. All of them work by simply dragging, connecting, and deploying nodes, just like Hello World. The code blocks are JavaScript that you can paste directly into a function node.


1. Threshold Alert

Goal: Send a Slack notification when a temperature tag reaches 80℃ or higher.

inject (5s) ─▶ 태그값 읽기 (TAG_TEMPERATURE) ─▶ function (임계값 체크) ─▶ switch ─▶ slack out

function:

const v = parseFloat(msg.payload.value);
msg.over = (v >= 80);
msg.temp = v;
return msg;

switch: condition msg.over is true → pass. 🔥 온도 경보 ${msg.temp}℃ in the message of slack out (or email/telegram).

Hysteresis

To prevent chattering near the threshold (80↔80.1), it is better to send the alarm only on the rising edge and to send it again only when the value rises again after being cleared. Use flow.set('lastAlert', true) to remember the state and trigger only at the toggle point.


2. Summing Multiple Tags and Writing to a New Tag (Calculated Value)

Goal: TAG_LINE1_QTY + TAG_LINE2_QTY + TAG_LINE3_QTY → refresh TAG_PLANT_TOTAL_QTY every second.

inject (1s) ─▶ 태그값 읽기 ×3 (병렬) ─▶ join ─▶ function (sum) ─▶ 태그값 쓰기

join: mode manual, combine array, key msg.topic, count 3. Attach a change node to the output of each tag value read to assign msg.topic differently as line1/line2/line3.

function:

const sum = msg.payload.reduce(
(a, p) => a + (parseFloat(p.value) || 0), 0);
return { tagId: 'TAG_PLANT_TOTAL_QTY', payload: String(sum) };
Difference from the formula feature

PlantPulse itself provides a formula tag feature. For simple arithmetic, handling it there is faster and more stable. Node-RED is more powerful when external APIs / MQTT / time conditions / conditional branching are mixed in.


3. CSV Logging (Per Minute)

Goal: Every minute, append the values of 5 key tags to local disk as a single CSV line.

inject (1m) ─▶ 태그값 읽기 ×5 ─▶ join ─▶ function (CSV 한 줄) ─▶ file (append)

function:

const ts = new Date().toISOString();
const cols = msg.payload.map(p => (p.value || '').replace(/,/g, ''));
msg.payload = [ts, ...cols].join(',') + '\n';
msg.filename = '/data1/pp-data/node-red/log/tags-' + ts.slice(0, 10) + '.csv';
return msg;

file node: Action append to file, Add newline off.

Disk location

The Node-RED userDir is /data1/pp-data/node-red. If you place the CSV files under it as well, they are included in the gateway backup policy.


4. Publishing in Real Time to an External SCADA over MQTT

(See MQTT for detailed settings.) A quick one-line pattern:

inject (1s) ─▶ 태그값 읽기 ─▶ change (topic=plant/${tag_id}/value) ─▶ mqtt out

5. Bringing Values from an External REST API into a Tag (Reverse Integration)

Goal: Record the outdoor temperature from an external weather API every 5 minutes into the virtual tag TAG_OUTDOOR_TEMP.

inject (5m) ─▶ http request (GET https://api.example.com/weather?...) ─▶ function ─▶ 태그값 쓰기

function:

return { tagId: 'TAG_OUTDOOR_TEMP', payload: String(msg.payload.main.temp) };

This value can be used like an ordinary tag on every PlantPulse screen / chart / external SCADA.


6. Daily Report Email at the Start of the Workday

Goal: Every morning at 7 a.m., email the average/maximum/minimum values of the previous 24 hours.

inject (cron: 0 7 * * *) ─▶ http request (GET /ui/opcua/history?...) ─▶ function (집계) ─▶ email

function:

const points = msg.payload.points || [];
const vs = points.map(p => parseFloat(p.value)).filter(v => !isNaN(v));
const avg = vs.reduce((a,b)=>a+b,0) / vs.length;
msg.topic = '[일일 리포트] 어제의 ' + msg.payload.tag_id;
msg.payload = '평균: ' + avg.toFixed(2)
+ '\n최대: ' + Math.max(...vs)
+ '\n최소: ' + Math.min(...vs);
return msg;

7. Simultaneous Branching to Slack + DB on Alarm

inject (1s) ─▶ 태그값 읽기 ─▶ switch (정상/비정상) ─▶┬─▶ slack out
└─▶ http request (POST /alerts)

The two nodes at the end of the abnormal branch (slack out, http request) receive the same message simultaneously.


8. Unit/Scale Conversion (4-20mA → bar)

inject (1s) ─▶ 태그값 읽기 (TAG_RAW_MA) ─▶ function (스케일) ─▶ 태그값 쓰기 (TAG_PRESSURE_BAR)

function:

const raw = parseFloat(msg.payload.value);
const ma = (raw / 32767) * 20;
const bar = Math.max(0, ((ma - 4) / (20 - 4)) * 100);
return { tagId: 'TAG_PRESSURE_BAR', payload: bar.toFixed(2) };

9. Gateway Self Health Check → Telegram

Poll the EDGE system tags shown in the OPC-UA viewer (/ui/opcua) as they are.

inject (30s) ─▶ 태그값 읽기 (TAG_EDGE_..._OPC_CONNECTED_COUNT) ─▶ function ─▶ telegram

If the value drops to 0, all PLCs are disconnected → notify immediately.


10. Polling-Free Real Time with OPC-UA Subscribe (Edge → Edge)

inject (once) ─▶ OpcUa-Item ×N ─▶ join ─▶ OpcUa-Subscribe ─▶ function (정규화) ─▶ 태그값 쓰기

Receive only change events from another company's OPC-UA server and mirror them directly onto our gateway's tags — a real-time gateway bridge.

For detailed OPC-UA node settings, see the OPC-UA node page.


11. Sending to the Cloud with Sparkplug B

inject (5s) ─▶ 태그값 읽기 ×N ─▶ function (metrics 배열 만들기) ─▶ sparkplug device out

PlantPulse also performs Sparkplug transmission on its own (고급 / 통합 파트너용 → Sparkplug B). Use direct transmission from Node-RED only when you need to customize Sparkplug behavior. For detailed settings, see the Sparkplug B node page.


12. Generating a Chart Image to Attach to an Alarm Message

By combining Node-RED's node-red-contrib-image-output + chart.js or the external QuickChart API, you can send a "trend over the past hour" graph to Slack along with the alarm — allowing operators to make an immediate judgment.


Next Steps