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 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Unique device identifier (MQTT username and client ID) |
| Access Token | your_access_token_here | 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.
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 = "YOUR_DEVICE_ID";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.