How to Read S6000U Data via EG5120 and Send to Blynk Cloud by MQTT

How to Read S6000U Data via EG5120 and Send to Blynk Cloud by MQTT

1. Overview

This guide outlines the integration of the S6000U multi-sensor (Temperature, Humidity, Light, Noise, etc.) with the Blynk Cloud platform via the Robustel EG5120 Industrial Edge Gateway.

Architecture:

  1. Field Layer: The S6000U sensor captures environmental metrics and transmits them to the Robustel EG5120 via a wired RS485 (Modbus RTU) connection.
  2. Edge Layer: The gateway bridges the physical serial interface to a local TCP Server (Port 5002). The internal Node-RED engine polls this data, parses the hexadecimal, and formats it into a JSON payload.
  3. Cloud Layer: Node-RED transmits the processed data to Blynk Cloud using the MQTT protocol.

2. Prerequisites

  • Hardware:
    • Robustel EG5120 Gateway (Powered on and Internet-connected).
    • S6000U Sensor (Connected to the gateway's RS485 interface).
  • Software:
    • Blynk Console Account.
    • RobustOS (Gateway Web Interface) access.
  • Credentials:
    • Blynk Auth Token (This will be used as the MQTT Password).
    • MQTT Broker Address: sgp1.blynk.cloud(This addres is up to your region and choose the right one ).

3. Step-by-Step Configuration

Step 1: Configure Blynk Console (Cloud Side)

1. Create Template:

  • Go to Developer Zone > My Templates > + New Template.
  • Name: S6000U MQTT Monitor.
  • Hardware: Other.
  • Connection Type: WiFi (or Ethernet).
  • Click Done.

2. Set Datastreams:
To ensure the JSON payload in Node-RED maps correctly to Blynk, create the following Virtual Pins.

  • Go to the Datastreams tab > + New Datastream > Virtual Pin.
  • Configure them as follows:

Virtual Pin

Name

Data Type

Units

Min/Max

V1

Temperature

Double

°C

-20 / 80

V2

Humidity

Double

%

0 / 100

V3

Light Level

Integer

lx

0 / 65535

V4

Noise

Double

dB

30 / 130

V5

Pressure

Double

hPa

0 / 2000

V6

TOF Distance

Integer

mm

0 / 4000

V7

Tilt Y

Integer

°

-90 / 90

V8

Accel X

Double

g

-10 / 10

V9

Accel Y

Double

g

-10 / 10

V10

Accel Z

Double

g

-10 / 10

V11

Device SN

String

None

-

V12

Event Count

Integer

None

0 / 1000

V13

Last Event

String

None

-



  • Click Save And Apply.

3. Create a Device:

  • Go to Devices > + New Device > From template.
  • Select S6000U MQTT Monitor.
  • Name the device (e.g., "EG5120-Gateway").
  • Important: Once created, go to the Device Dashboard and copy the Auth Token to your clipboard. You will need this for the Node-RED configuration.

Step 2: Create Web Dashboard

  1. Click on the Web Dashboard tab in your Template settings.
  2. Drag widgets from the Widget Box to the canvas:
    • Gauges: Link to V1 (Temp), V2 (Humidity), V4 (Noise).
    • Label Values: Link to V11 (SN), V13 (Last Event).
    • Charts: Link to V3 (Light) or V12 (Event Count).
  1. Click Save to apply the dashboard layout.

Step 3: Configure Robustel EG5120 (Edge Side)

  1. Serial Port Mapping:

Log in to the EG5120. Go to Interface > Serial Port.

    • Edit the RS485 port settings (Baud: 115200, 8N1).

    • Application Mode: TCP Server.
    • Local Port: 5002.
    • Click Submit and Save & Apply.


  1. Enable Node-RED:
    • Go to Development> Node-RED.
    • Enable the service and the editor.

    • Once you click Open Editor button, you can see the Node-RED editor page as follow.


Step 4: Node-RED Flow Configuration (MQTT Logic)

1. Open Editor:

  • Click the Open Editor button in the RobustOS Node-RED menu.

2. Import Flow Code:

  • In the Node-RED editor, click the Hamburger Menu (top right) > Import.
  • Copy and paste the JSON Code provided as below.
  • Click Import.

Note: See the example JSON for Node-RED is shown as below.

[
{
"id": "7649d21c43153579",
"type": "tab",
"label": "S6000UtoBlynkByMQTT_BatchSend",
"disabled": false,
"info": "Uses Blynk batch reporting (ds topic + JSON) to avoid single message limitations."
},
{
"id": "27045b6378e352df",
"type": "inject",
"z": "7649d21c43153579",
"name": "Poll Sensors (5s)",
"props": [
{
"p": "payload"
}
],
"repeat": "5",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 80,
"wires": [
[
"c982390885e3c150"
]
]
},
{
"id": "c982390885e3c150",
"type": "function",
"z": "7649d21c43153579",
"name": "CMD: Sensor Data (0x100, 14 Regs)",
"func": "var slaveId = 0x01;\nvar funcCode = 0x04;\nvar startAddr = 0x0100;\nvar readLen = 14;\n\nvar buffer = Buffer.alloc(6);\nbuffer.writeUInt8(slaveId, 0);\nbuffer.writeUInt8(funcCode, 1);\nbuffer.writeUInt16BE(startAddr, 2);\nbuffer.writeUInt16BE(readLen, 4);\n\nfunction calculateCRC(buf) {\n var crc = 0xFFFF;\n for (var pos = 0; pos < buf.length; pos++) {\n crc ^= buf[pos];\n for (var i = 8; i !== 0; i--) {\n if ((crc & 0x0001) !== 0) {\n crc >>= 1;\n crc ^= 0xA001;\n } else {\n crc >>= 1;\n }\n }\n }\n return crc;\n}\nvar crcResult = calculateCRC(buffer);\n\nvar finalBuffer = Buffer.alloc(8);\nbuffer.copy(finalBuffer, 0, 0, 6);\nfinalBuffer.writeUInt8(crcResult & 0xFF, 6);\nfinalBuffer.writeUInt8((crcResult >> 8) & 0xFF, 7);\n\nmsg.payload = finalBuffer;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 410,
"y": 80,
"wires": [
[
"461e1a53b516ff83"
]
]
},
{
"id": "461e1a53b516ff83",
"type": "tcp request",
"z": "7649d21c43153579",
"name": "TCP: 127.0.0.1:5002",
"server": "127.0.0.1",
"port": "5002",
"out": "time",
"splitc": "200",
"x": 700,
"y": 80,
"wires": [
[
"61a8cc2c4ef228cc",
"d965e9900ec5e4f4"
]
]
},
{
"id": "61a8cc2c4ef228cc",
"type": "function",
"z": "7649d21c43153579",
"name": "Parse & Store: Sensor Data (V1-V10)",
"func": "var buf = msg.payload;\n\nfunction getFloatFromBuffer(buf, offset) {\n var lword = buf.readUInt16BE(offset);\n var hword = buf.readUInt16BE(offset + 2);\n var uint32Value = (hword << 16) | lword;\n let buffer = new ArrayBuffer(4);\n let intView = new Uint32Array(buffer);\n let floatView = new Float32Array(buffer);\n intView[0] = uint32Value;\n return floatView[0];\n}\n\nif (!Buffer.isBuffer(buf) || buf.length < 33) {\n return null;\n}\nif (buf.readUInt8(1) !== 0x04) return null;\n\nvar tempRaw = buf.readUInt16BE(3);\nvar temp = (tempRaw / 100.0).toFixed(1);\nvar humiRaw = buf.readUInt16BE(5);\nvar lightRaw = buf.readUInt16BE(7);\nvar noiseRaw = buf.readUInt16BE(9);\nvar pressureRaw = getFloatFromBuffer(buf, 11);\nvar pressure = pressureRaw.toFixed(0);\nvar tofRaw = buf.readUInt16BE(15);\nvar tiltRaw = buf.readUInt16BE(17);\nvar accXRaw = getFloatFromBuffer(buf, 19);\nvar accYRaw = getFloatFromBuffer(buf, 23);\nvar accZRaw = getFloatFromBuffer(buf, 27);\nvar gravity_constant = 9.82;\nvar accX = (accXRaw / 1000.0 * gravity_constant).toFixed(2);\nvar accY = (accYRaw / 1000.0 * gravity_constant).toFixed(2);\nvar accZ = (accZRaw / 1000.0 * gravity_constant).toFixed(2);\n\n// Simulate Random Lux \nvar minLux = 0, maxLux = 0;\nswitch (lightRaw) {\n case 0: minLux = 0; maxLux = 5; break;\n case 1: minLux = 45; maxLux = 50; break;\n case 2: minLux = 95; maxLux = 100; break;\n case 3: minLux = 490; maxLux = 500; break; // 101~500 lux\n case 4: minLux = 1800; maxLux = 2000; break; // 501~2000 lux\n case 5: minLux = 2001; maxLux = 5000; break; // 2000 lux+ \n default: minLux = 0; maxLux = 0;\n}\nvar randomLux = Math.floor(Math.random() * (maxLux - minLux + 1)) + minLux;\n\n// Save to flow context\nflow.set('V1', parseFloat(temp));\nflow.set('V2', humiRaw);\nflow.set('V3', randomLux);\nflow.set('V4', noiseRaw);\nflow.set('V5', parseFloat(pressure));\nflow.set('V6', tofRaw);\nflow.set('V7', tiltRaw);\nflow.set('V8', parseFloat(accX));\nflow.set('V9', parseFloat(accY));\nflow.set('V10', parseFloat(accZ));\n\n// Trigger Batch Send\nreturn { payload: \"trigger\" };",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 180,
"wires": [
[
"6b499878206d2899",
"7d383842c1619a93"
]
]
},
{
"id": "d965e9900ec5e4f4",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: Raw Response",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 930,
"y": 80,
"wires": []
},
{
"id": "6b499878206d2899",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: Data Store (V1-V10)",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 670,
"y": 180,
"wires": []
},
{
"id": "27b7d78d4c798701",
"type": "inject",
"z": "7649d21c43153579",
"name": "Poll Events (12s)",
"props": [
{
"p": "payload"
}
],
"repeat": "12",
"crontab": "",
"once": true,
"onceDelay": "2",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 360,
"wires": [
[
"7788fa1222c1b2b8"
]
]
},
{
"id": "7788fa1222c1b2b8",
"type": "function",
"z": "7649d21c43153579",
"name": "CMD: Events (0x7100, 2 Regs)",
"func": "var slaveId = 0x01;\nvar funcCode = 0x04;\nvar startAddr = 0x7100;\nvar readLen = 2;\n\nvar buffer = Buffer.alloc(6);\nbuffer.writeUInt8(slaveId, 0);\nbuffer.writeUInt8(funcCode, 1);\nbuffer.writeUInt16BE(startAddr, 2);\nbuffer.writeUInt16BE(readLen, 4);\n\nfunction calculateCRC(buf) {\n var crc = 0xFFFF;\n for (var pos = 0; pos < buf.length; pos++) {\n crc ^= buf[pos];\n for (var i = 8; i !== 0; i--) {\n if ((crc & 0x0001) !== 0) {\n crc >>= 1;\n crc ^= 0xA001;\n } else {\n crc >>= 1;\n }\n }\n }\n return crc;\n}\nvar crcResult = calculateCRC(buffer);\n\nvar finalBuffer = Buffer.alloc(8);\nbuffer.copy(finalBuffer, 0, 0, 6);\nfinalBuffer.writeUInt8(crcResult & 0xFF, 6);\nfinalBuffer.writeUInt8((crcResult >> 8) & 0xFF, 7);\n\nmsg.payload = finalBuffer;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 360,
"wires": [
[
"61f185f403e2c69d"
]
]
},
{
"id": "61f185f403e2c69d",
"type": "tcp request",
"z": "7649d21c43153579",
"name": "TCP: 127.0.0.1:5002",
"server": "127.0.0.1",
"port": "5002",
"out": "time",
"splitc": "200",
"x": 700,
"y": 360,
"wires": [
[
"77b28203d922a9cf"
]
]
},
{
"id": "77b28203d922a9cf",
"type": "function",
"z": "7649d21c43153579",
"name": "Parse & Store: Events (V12, V13)",
"func": "var buf = msg.payload;\nif (!Buffer.isBuffer(buf) || buf.length < 9) return null;\nif (buf.readUInt8(1) !== 0x04) return null;\nvar eventCount = buf.readUInt16BE(3);\nvar eventCode = buf.readUInt16BE(5);\nvar eventMsg = \"Normal\";\nif (eventCount > 0) {\n switch(eventCode) {\n case 0x01: eventMsg = \"Temp High\"; break;\n case 0x02: eventMsg = \"Temp Low\"; break;\n case 0x03: eventMsg = \"Humidity High\"; break;\n case 0x04: eventMsg = \"Humidity Low\"; break;\n case 0x05: eventMsg = \"Light High\"; break;\n // New Events\n case 0x06: eventMsg = \"Light Low\"; break;\n case 0x07: eventMsg = \"Noise High\"; break;\n case 0x08: eventMsg = \"Noise Low\"; break;\n case 0x09: eventMsg = \"Pressure High\"; break;\n case 0x0A: eventMsg = \"Pressure Low\"; break;\n case 0x0B: eventMsg = \"ToF Distance High\"; break;\n case 0x0C: eventMsg = \"ToF Distance Low\"; break;\n case 0x0D: eventMsg = \"Tilt High\"; break;\n case 0x0E: eventMsg = \"Tilt Low\"; break;\n default: eventMsg = \"Code: \" + eventCode;\n }\n}\n\n// Save to flow context\nflow.set('V12', eventCount);\nflow.set('V13', eventMsg);\n\n// Trigger Batch Send\nreturn { payload: \"trigger\" };",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 420,
"wires": [
[
"7d383842c1619a93",
"1df3889c162580cc"
]
]
},
{
"id": "14101e1493b82142",
"type": "inject",
"z": "7649d21c43153579",
"name": "Poll SN (18s)",
"props": [
{
"p": "payload"
}
],
"repeat": "18",
"crontab": "",
"once": true,
"onceDelay": "3",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 540,
"wires": [
[
"9398ac3577d6118d"
]
]
},
{
"id": "9398ac3577d6118d",
"type": "function",
"z": "7649d21c43153579",
"name": "CMD: SN (0x7030, 16 Regs)",
"func": "var slaveId = 0x01;\nvar funcCode = 0x04;\nvar startAddr = 0x7030;\nvar readLen = 16;\n\nvar buffer = Buffer.alloc(6);\nbuffer.writeUInt8(slaveId, 0);\nbuffer.writeUInt8(funcCode, 1);\nbuffer.writeUInt16BE(startAddr, 2);\nbuffer.writeUInt16BE(readLen, 4);\n\nfunction calculateCRC(buf) {\n var crc = 0xFFFF;\n for (var pos = 0; pos < buf.length; pos++) {\n crc ^= buf[pos];\n for (var i = 8; i !== 0; i--) {\n if ((crc & 0x0001) !== 0) {\n crc >>= 1;\n crc ^= 0xA001;\n } else {\n crc >>= 1;\n }\n }\n }\n return crc;\n}\nvar crcResult = calculateCRC(buffer);\n\nvar finalBuffer = Buffer.alloc(8);\nbuffer.copy(finalBuffer, 0, 0, 6);\nfinalBuffer.writeUInt8(crcResult & 0xFF, 6);\nfinalBuffer.writeUInt8((crcResult >> 8) & 0xFF, 7);\n\nmsg.payload = finalBuffer;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 540,
"wires": [
[
"a1969a5976b010c7"
]
]
},
{
"id": "a1969a5976b010c7",
"type": "tcp request",
"z": "7649d21c43153579",
"name": "TCP: 127.0.0.1:5002",
"server": "127.0.0.1",
"port": "5002",
"out": "time",
"splitc": "200",
"x": 700,
"y": 540,
"wires": [
[
"6af76a8d8e0e7a2b"
]
]
},
{
"id": "6af76a8d8e0e7a2b",
"type": "function",
"z": "7649d21c43153579",
"name": "Parse & Store: SN (V11)",
"func": "var buf = msg.payload;\nif (!Buffer.isBuffer(buf) || buf.length < 37) return null;\nif (buf.readUInt8(1) !== 0x04) return null;\nvar sn = buf.toString('ascii', 3, 35).replace(/\\u0000/g, '').trim();\n\n// Save to flow context\nflow.set('V11', sn);\n\n// Trigger Batch Send\nreturn { payload: \"trigger\" };",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 600,
"wires": [
[
"7d383842c1619a93",
"37f51b6ce6f15777"
]
]
},
{
"id": "37f51b6ce6f15777",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: Data Store (V11)",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 670,
"y": 600,
"wires": []
},
{
"id": "mqtt_out_node",
"type": "mqtt out",
"z": "7649d21c43153579",
"name": "Blynk MQTT (batch_ds)",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "c200ed436e2f4702",
"x": 1090,
"y": 660,
"wires": []
},
{
"id": "7d383842c1619a93",
"type": "delay",
"z": "7649d21c43153579",
"name": "Rate Limit (1 msg/s)",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"allowrate": true,
"outputs": 1,
"x": 780,
"y": 480,
"wires": [
[
"b1b423c10a3014a6",
"61b7829871578322"
]
]
},
{
"id": "b1b423c10a3014a6",
"type": "function",
"z": "7649d21c43153579",
"name": "Batch Send to Blynk (ds)",
"func": "// Get stored data from flow context\nvar V1 = flow.get('V1') || 0;\nvar V2 = flow.get('V2') || 0;\nvar V3 = flow.get('V3') || 0;\nvar V4 = flow.get('V4') || 0;\nvar V5 = flow.get('V5') || 0;\nvar V6 = flow.get('V6') || 0;\nvar V7 = flow.get('V7') || 0;\nvar V8 = flow.get('V8') || 0;\nvar V9 = flow.get('V9') || 0;\nvar V10 = flow.get('V10') || 0;\nvar V11 = flow.get('V11') || \"Unknown\";\nvar V12 = flow.get('V12') || 0;\nvar V13 = flow.get('V13') || \"Normal\";\n\n// Construct JSON Payload\nvar jsonPayload = {\n \"Temperature\": V1,\n \"Humidity\": V2,\n \"Light Level\": V3,\n \"Noise\": V4,\n \"Pressure\": V5,\n \"TOF Distance\": V6,\n \"Tilt Y\": V7,\n \"Accel X\": V8,\n \"Accel Y\": V9,\n \"Accel Z\": V10,\n \"Device SN\": V11,\n \"Event Count\": V12,\n \"Last Event\": V13\n};\n\n// Set Topic and Payload\nmsg.topic = \"batch_ds\"; // Send to batch data topic\nmsg.payload = JSON.stringify(jsonPayload); // Payload as JSON string\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1050,
"y": 480,
"wires": [
[
"mqtt_out_node",
"2854e4fa0855bbc7"
]
]
},
{
"id": "61b7829871578322",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: JSON Payload",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"statusVal": "",
"statusType": "auto",
"x": 1000,
"y": 540,
"wires": []
},
{
"id": "1df3889c162580cc",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: Data Store (V12-V13)",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 670,
"y": 420,
"wires": []
},
{
"id": "2854e4fa0855bbc7",
"type": "debug",
"z": "7649d21c43153579",
"name": "Debug: Upload Payload",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1070,
"y": 380,
"wires": []
},
{
"id": "c200ed436e2f4702",
"type": "mqtt-broker",
"name": "BLYNK Cloud MQTT",
"broker": "sgp1.blynk.cloud",
"port": "1883",
"tls": "f68fa617284cf85c",
"clientid": "EG5120-NodeRED-Client",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "45",
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": "0"
},
{
"id": "f68fa617284cf85c",
"type": "tls-config",
"name": "",
"cert": "",
"key": "",
"ca": "",
"certname": "",
"keyname": "",
"caname": "",
"servername": "",
"verifyservercert": true,
"alpnprotocol": ""
}
]

3. Configure MQTT Credentials:

  • Locate the purple node named Blynk MQTT (batch_ds) on the right side of the flow.
  • Double-click the node to open its properties.
  • Click the pencil icon next to the "Server" field (sgp1.blynk.cloud) to edit the config node.
  • Connection Tab:
    • Server: sgp1.blynk.cloud
    • Port: 1883
    • Client ID: EG5120-NodeRED-Client (or leave default).
  • Security Tab:
    • Username: device
    • Password: [PASTE YOUR BLYNK AUTH TOKEN HERE]
  • Click Update to save the config.
  • Click Done to close the node properties.

4. Deploy:

  • Click the red Deploy button in the top-right corner.

4. Final Verification

  1. Node-RED Debug:
    • Open the Debug sidebar (bug icon) in Node-RED.
    • You should see messages appearing every few seconds under "Debug: Upload Payload".
    • The status under the "Blynk MQTT" node should say "connected".



  1. Blynk Console:
    • Open your Device Dashboard in the Blynk Console.
    • Verify that the widgets are updating with real-time data from the sensor.
    • The "Device SN" and "Last Event" fields should display text strings.


Revision History

Version

Date

Author

Changes

1.0

2025-11-24

Steven Lin

Initial version