Node.js MQTT Client for SiliconWit.io
In this tutorial, you will learn how to build a Node.js MQTT client that simulates an IoT device sending sensor telemetry data to the SiliconWit.io platform. The client connects to the SiliconWit.io MQTT broker over a secure TLS connection and publishes random sensor readings at regular intervals.
Node.js is well-suited for IoT applications thanks to its event-driven architecture and the mature mqtt npm package. This tutorial is useful for building device simulators, IoT gateways, or server-side MQTT integrations.
What You Will Learn
Section titled “What You Will Learn”- How to install and configure the
mqttnpm package - How to establish a secure TLS connection to the SiliconWit.io MQTT broker
- How to authenticate using device credentials
- How to publish JSON telemetry data on a timed interval
- How to handle connection events and automatic reconnection
Prerequisites
Section titled “Prerequisites”| Requirement | Details |
|---|---|
| Node.js | Version 18 or later |
| npm | Included with Node.js |
| SiliconWit.io Account | Free IoT platform account |
| A registered device | Created from the SiliconWit.io dashboard |
Verify your Node.js installation:
node --versionnpm --versionYou will need the following credentials from your SiliconWit.io dashboard after registering a device:
| Credential | Example | Description |
|---|---|---|
| Device ID | SWD-XXXXXX | Unique device identifier (MQTT username and client ID) |
| Access Token | your-access-token | MQTT password |
| Publish Topic | d/{device_id}/t | Topic for sending sensor data (d = device, t = telemetry) |
Keep your access token secure. Never share it publicly or commit it to version control.
Create Your Device on SiliconWit.io
Section titled “Create Your Device on SiliconWit.io”Before writing any code, set up a device on the platform so you have credentials to connect with.
- Log in to your SiliconWit.io dashboard.
- Navigate to Devices and click Add Device.
- Choose a device template or select Start from Scratch.
- Fill in the required fields:
- Device Name:
Node.js Sensor - Device Type: Sensor
- Data Interval: 10 seconds (for testing; increase for production)
- Device Name:
- In the Data Fields section, configure the fields your device will send. You can add them manually or import the following JSON:
[ { "name": "temperature", "label": "Temperature", "unit": "°C" }, { "name": "humidity", "label": "Humidity", "unit": "%" }]- Click Create Device.
- Copy your Device ID and Access Token from the device detail page. You will need these in the code below.
Step 1: Set Up the Project
Section titled “Step 1: Set Up the Project”Create a new project directory and initialize it:
mkdir siliconwit-node-clientcd siliconwit-node-clientnpm init -yInstall the mqtt package:
npm install mqttYour project structure should look like this:
siliconwit-node-client/├── node_modules/├── index.js├── package.json└── package-lock.jsonStep 2: Understand the Connection Architecture
Section titled “Step 2: Understand the Connection Architecture”The Node.js client connects directly to the SiliconWit.io MQTT broker using the mqtts:// protocol (MQTT over TLS):
┌─────────────────────────────────────────────────────────┐│ SiliconWit.io Cloud ││ ││ Dashboard <--> MQTT Broker (TLS on port 8883) ││ | ││ Telemetry Topic ││ d/{device_id}/t │└────────────────────┬────────────────────────────────────┘ │ │ TLS 1.2 (port 8883) │┌────────────────────┴────────────────────────────────────┐│ Node.js Client (mqtt package) ││ ││ - Connects with mqtts:// protocol ││ - Authenticates with device_id + access_token ││ - Publishes simulated sensor data every 10 seconds │└─────────────────────────────────────────────────────────┘Step 3: Configure the TLS Connection
Section titled “Step 3: Configure the TLS Connection”The mqtt npm package supports TLS natively via the mqtts:// URL scheme. Node.js uses its built-in TLS module, which trusts the same CA certificates as your operating system.
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://mqtt.siliconwit.io:8883", { clientId: DEVICE_ID, username: DEVICE_ID, password: ACCESS_TOKEN,});The mqtts:// prefix tells the client to use MQTT over TLS. No additional certificate configuration is needed.
Step 4: Simulate Sensor Data
Section titled “Step 4: Simulate Sensor Data”The device simulator generates random sensor readings that mimic a real IoT device. Each telemetry message includes temperature, humidity, and a battery voltage level.
function generateSensorData() { return { temperature: parseFloat((20 + Math.random() * 15).toFixed(1)), humidity: parseFloat((30 + Math.random() * 50).toFixed(1)), battery_voltage: parseFloat((3.0 + Math.random() * 1.2).toFixed(2)), };}| Field | Type | Range | Description |
|---|---|---|---|
temperature | float | 20.0 - 35.0 | Simulated temperature in Celsius |
humidity | float | 30.0 - 80.0 | Simulated relative humidity percentage |
battery_voltage | float | 3.00 - 4.20 | Simulated battery level in volts |
Step 5: Publish Telemetry in a Loop
Section titled “Step 5: Publish Telemetry in a Loop”Use setInterval to publish telemetry data at regular intervals:
const PUBLISH_TOPIC = `d/${DEVICE_ID}/t`;const TELEMETRY_INTERVAL = 10000; // 10 seconds in milliseconds
setInterval(() => { if (client.connected) { const data = generateSensorData(); const payload = JSON.stringify(data); client.publish(PUBLISH_TOPIC, payload, { qos: 1 }); console.log(`[TELEMETRY] Sent: ${payload}`); }}, TELEMETRY_INTERVAL);Step 6: Full Code
Section titled “Step 6: Full Code”Create a file called index.js with the following complete code:
const mqtt = require("mqtt");
// ========== SILICONWIT IO MQTT CONFIGURATION ==========const MQTT_BROKER = "mqtts://mqtt.siliconwit.io:8883";const DEVICE_ID = "SWD-XXXXXX";const ACCESS_TOKEN = "your-access-token";const PUBLISH_TOPIC = `d/${DEVICE_ID}/t`;
// ========== TIMING ==========const TELEMETRY_INTERVAL = 10000; // milliseconds
// ========== SENSOR SIMULATION ==========function generateSensorData() { return { temperature: parseFloat((20 + Math.random() * 15).toFixed(1)), humidity: parseFloat((30 + Math.random() * 50).toFixed(1)), battery_voltage: parseFloat((3.0 + Math.random() * 1.2).toFixed(2)), };}
// ========== MAIN ==========console.log("=== Node.js MQTT Device Simulator -> SiliconWit.io ===\n");
// Create MQTT client with TLSconst client = mqtt.connect(MQTT_BROKER, { clientId: DEVICE_ID, username: DEVICE_ID, password: ACCESS_TOKEN, protocol: "mqtts", reconnectPeriod: 5000, connectTimeout: 30000, keepalive: 60,});
// ========== EVENT HANDLERS ==========client.on("connect", () => { console.log("[MQTT] Connected to SiliconWit.io");
// Send initial telemetry immediately on connect const data = generateSensorData(); const payload = JSON.stringify(data); client.publish(PUBLISH_TOPIC, payload, { qos: 1 }); console.log(`[TELEMETRY] Sent: ${payload}`);});
client.on("reconnect", () => { console.log("[MQTT] Reconnecting...");});
client.on("disconnect", () => { console.log("[MQTT] Disconnected");});
client.on("error", (err) => { console.error(`[MQTT] Error: ${err.message}`);});
client.on("offline", () => { console.log("[MQTT] Client offline");});
// ========== TELEMETRY LOOP ==========let messageCount = 0;
const telemetryInterval = setInterval(() => { if (client.connected) { const data = generateSensorData(); const payload = JSON.stringify(data);
client.publish(PUBLISH_TOPIC, payload, { qos: 1 }, (err) => { if (err) { console.error(`[TELEMETRY] Publish error: ${err.message}`); } else { messageCount++; console.log(`[TELEMETRY] #${messageCount} Sent: ${payload}`); } }); } else { console.log("[MQTT] Not connected, skipping telemetry..."); }}, TELEMETRY_INTERVAL);
// ========== GRACEFUL SHUTDOWN ==========function shutdown() { console.log("\n[INFO] Shutting down..."); clearInterval(telemetryInterval); client.end(false, {}, () => { console.log(`[INFO] Disconnected. Sent ${messageCount} messages. Goodbye.`); process.exit(0); });}
process.on("SIGINT", shutdown);process.on("SIGTERM", shutdown);Run the simulator:
node index.jsExpected output:
=== Node.js MQTT Device Simulator -> SiliconWit.io ===
[MQTT] Connected to SiliconWit.io[TELEMETRY] Sent: {"temperature":27.3,"humidity":52.1,"battery_voltage":3.85}[TELEMETRY] #1 Sent: {"temperature":24.8,"humidity":61.4,"battery_voltage":4.02}[TELEMETRY] #2 Sent: {"temperature":31.2,"humidity":38.7,"battery_voltage":3.54}Press Ctrl+C to stop the simulator gracefully.
Step 7: View Data on SiliconWit.io
Section titled “Step 7: View Data on SiliconWit.io”- Log in to your SiliconWit.io dashboard.
- Navigate to your registered device.
- You should see temperature, humidity, and battery voltage updating every 10 seconds.
- SiliconWit.io automatically detects and displays each data field.
Step 8: Running as a Background Process (Optional)
Section titled “Step 8: Running as a Background Process (Optional)”For long-running simulators or production gateways, you can use a process manager like pm2:
npm install -g pm2pm2 start index.js --name siliconwit-simulatorpm2 savepm2 startupUseful pm2 commands:
| Command | Description |
|---|---|
pm2 logs siliconwit-simulator | View live logs |
pm2 restart siliconwit-simulator | Restart the process |
pm2 stop siliconwit-simulator | Stop the process |
pm2 status | Show all running processes |
Troubleshooting
Section titled “Troubleshooting”Connection Issues
Section titled “Connection Issues”| Symptom | Cause | Solution |
|---|---|---|
ECONNREFUSED | Wrong broker address or port | Verify the MQTT_BROKER URL includes mqtts:// and port 8883. |
UNABLE_TO_VERIFY_LEAF_SIGNATURE | CA certificate issue | Update Node.js to the latest LTS version. Run npm config set strict-ssl false as a workaround. |
Error: Not authorized | Invalid credentials | Verify DEVICE_ID and ACCESS_TOKEN match your SiliconWit.io dashboard. |
ETIMEOUT | Firewall blocking port 8883 | Check that outbound port 8883 is allowed on your network. |
Repeated reconnect events | Network instability | Check your internet connection. Increase reconnectPeriod. |
Publishing Issues
Section titled “Publishing Issues”| Symptom | Cause | Solution |
|---|---|---|
| Publish callback receives error | Client not connected | The client.connected check should prevent this. Verify connection. |
| Data not showing on dashboard | Wrong topic format | Topic must be exactly d/{device_id}/t. |
| Payload too large | JSON exceeds limit | SiliconWit.io accepts up to 10KB. Keep payloads small. |
Runtime Issues
Section titled “Runtime Issues”| Symptom | Cause | Solution |
|---|---|---|
Cannot find module 'mqtt' | Package not installed | Run npm install mqtt in the project directory. |
| High memory usage over time | Memory leak | Ensure you are not accumulating data in arrays or closures. |
| Process exits unexpectedly | Unhandled rejection | Add process.on('unhandledRejection', console.error) for debugging. |
Summary
Section titled “Summary”In this tutorial, you built a Node.js device simulator that:
- Connects securely to the SiliconWit.io MQTT broker over TLS using the
mqtts://protocol - Authenticates with your Device ID and Access Token
- Publishes simulated sensor data (temperature, humidity, battery voltage) as JSON every 10 seconds
- Handles automatic reconnection and graceful shutdown
- Can be run as a background service using pm2
This pattern is ideal for testing your SiliconWit.io setup, simulating multiple devices, or building Node.js IoT gateways that aggregate and forward data from connected sensors.